(int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned):I'll loose something?

Discussion in 'C Programming' started by pozz, Mar 18, 2011.

  1. pozz

    pozz Guest

    int x = <value>;
    int y = (int)((unsigned)x);

    The value of y is the same of x for any starting value and C
    implementation?

    unsigned int x = <value>;
    unsigned int y = (unsigned)((int)x);

    And in this case?

    In other words, is there a risk to loose any value switching from
    signed to unsigned and viceversa representation of integers?
     
    pozz, Mar 18, 2011
    #1
    1. Advertising

  2. Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned): I'll loose something?

    pozz <> writes:

    > int x = <value>;
    > int y = (int)((unsigned)x);
    >
    > The value of y is the same of x for any starting value and C
    > implementation?
    >
    > unsigned int x = <value>;
    > unsigned int y = (unsigned)((int)x);
    >
    > And in this case?


    Neither case is safe. Both can involve an out-of-range conversion from
    unsigned to int. This is something that you might choose to live with.
    In most cases the conversion is implementation defined[1] and will be
    defined to do the "obvious" thing.

    You can avoid a conversion by "type punning" using either a union or a
    pointer conversion:

    unsigned u = /* ... */;
    int s = *(int *)&u;

    This swaps the problem to one of representations. Rather than relying
    on the conversion of an out of range value you reply on there being no
    unsigned int bit patterns that are not valid signed int representations.
    I don't know of any implementations where this is a problem but it is
    permitted (by 6.2.6.2 paragraph 2).

    As I've alread posted, you can get round both issues if you really need
    to.

    <snip>

    [1] The C standard includes permission to raise a signal but this is not
    often done as far as I know.

    --
    Ben.
     
    Ben Bacarisse, Mar 18, 2011
    #2
    1. Advertising

  3. pozz

    Eric Sosman Guest

    On 3/18/2011 6:06 AM, pozz wrote:
    > int x =<value>;
    > int y = (int)((unsigned)x);
    >
    > The value of y is the same of x for any starting value and C
    > implementation?


    No. Suppose x is negative. Since an unsigned value cannot be
    negative, the (unsigned)x conversion produces a different value
    UINT_MAX+x+1. This value is quite likely to be larger than INT_MAX,
    so converting it to plain int again produces an implementation-defined
    result or raises an implementation-defined signal.

    On most C implementations the "implementation-defined result"
    turns out to be x, but that's not guaranteed by the language and
    can't be counted on for "any" C implementation.

    > unsigned int x =<value>;
    > unsigned int y = (unsigned)((int)x);
    >
    > And in this case?


    Similar problem: If the value of x is greater than INT_MAX,
    converting that value to int is problematic.

    > In other words, is there a risk to loose any value switching from
    > signed to unsigned and viceversa representation of integers?


    Yes. (By the way, "vice versa" is a two-word phrase. Also,
    "loose" is a perfectly good verb, but it doesn't mean "lose.")

    --
    Eric Sosman
    d
     
    Eric Sosman, Mar 18, 2011
    #3
  4. pozz

    pozz Guest

    Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) ->

    On 18 Mar, 12:46, Ben Bacarisse <> wrote:
    > Neither case is safe.  Both can involve an out-of-range conversion from
    > unsigned to int.


    Hmm..., and what happens with printf, for example:
    unsigned int x = UINT_MAX;
    printf ("x=%u\n", x);

    Is x converted to int (signed) when it is pushed onto the stack as an
    argument for printf? Or maybe it is untouched onto the stack when the
    parameter is one of the variable arguments (as happens in printf)?
     
    pozz, Mar 18, 2011
    #4
  5. pozz

    pozz Guest

    Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) ->

    On 18 Mar, 13:34, Eric Sosman <> wrote:
    > > In other words, is there a risk to loose any value switching from
    > > signed to unsigned and viceversa representation of integers?

    >
    >      Yes.  (By the way, "vice versa" is a two-word phrase.  Also,
    > "loose" is a perfectly good verb, but it doesn't mean "lose.")


    I'm sorry, I don't know C language as English languange :)
     
    pozz, Mar 18, 2011
    #5
  6. Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned): I'll loose something?

    pozz <> writes:

    > On 18 Mar, 12:46, Ben Bacarisse <> wrote:
    >> Neither case is safe.  Both can involve an out-of-range conversion from
    >> unsigned to int.

    >
    > Hmm..., and what happens with printf, for example:
    > unsigned int x = UINT_MAX;
    > printf ("x=%u\n", x);
    >
    > Is x converted to int (signed) when it is pushed onto the stack as an
    > argument for printf? Or maybe it is untouched onto the stack when the
    > parameter is one of the variable arguments (as happens in printf)?


    No, you are passing an unsigned int not an it. The default argument
    promotions don't affect unsigned int.

    --
    Ben.
     
    Ben Bacarisse, Mar 18, 2011
    #6
  7. Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned): I'll loose something?

    pozz <> writes:
    > On 18 Mar, 12:46, Ben Bacarisse <> wrote:
    >> Neither case is safe.  Both can involve an out-of-range conversion from
    >> unsigned to int.

    >
    > Hmm..., and what happens with printf, for example:
    > unsigned int x = UINT_MAX;
    > printf ("x=%u\n", x);
    >
    > Is x converted to int (signed) when it is pushed onto the stack as an
    > argument for printf? Or maybe it is untouched onto the stack when the
    > parameter is one of the variable arguments (as happens in printf)?


    No, there is no conversion and no problem. The value of x is passed
    as an argument to printf (this probably involves pushing it onto the
    stack in most implementations, but the mechanism is irrelevant).
    The "%u" tells printf to expect an unsigned argument -- which is
    exactly what you gave it. There's no int in sight (other than
    the value returned by printf).

    If you had used a "%d" format rather than "%u", then the behavior
    would be undefined. There would still be no *conversion*; instead,
    printf would most likely try to interpret the passed unsigned
    int value as if it were of type int. The behavior is likely
    to be what you'd expect, but the standard doesn't guarantee it.
    (There's a special-case guarantee for the case where the value is
    within the range of both types, but that doesn't apply here, since
    UINT_MAX is outside the range of int.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Mar 18, 2011
    #7
  8. pozz

    puppi Guest

    Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) ->

    On Mar 18, 7:06 am, pozz <> wrote:
    > int x = <value>;
    > int y = (int)((unsigned)x);
    >
    > The value of y is the same of x for any starting value and C
    > implementation?
    >
    > unsigned int x = <value>;
    > unsigned int y = (unsigned)((int)x);
    >
    > And in this case?
    >
    > In other words, is there a risk to loose any value switching from
    > signed to unsigned and viceversa representation of integers?


    No. There is no risk. Unsigned and signed integers are the same: they
    only differ in how the sign bit is interpreted. y will be exactly x,
    ALWAYS. If y was signed, on the other hand, the value could be
    different (if and only if it was interpreted as negative, i.e. the
    sign bit was set), but the binary content would be rigorously the
    same. Even in the case that y were signed, (unsigned)y would be
    exactly x. That's because since the binary content is not modified, a
    conversion that in the end converts back to the original type will
    mean exatcly the same thing.
     
    puppi, Mar 20, 2011
    #8
  9. Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned): I'll loose something?

    puppi <> writes:
    > On Mar 18, 7:06 am, pozz <> wrote:
    >> int x = <value>;
    >> int y = (int)((unsigned)x);
    >>
    >> The value of y is the same of x for any starting value and C
    >> implementation?
    >>
    >> unsigned int x = <value>;
    >> unsigned int y = (unsigned)((int)x);
    >>
    >> And in this case?
    >>
    >> In other words, is there a risk to loose any value switching from
    >> signed to unsigned and viceversa representation of integers?

    >
    > No. There is no risk. Unsigned and signed integers are the same: they
    > only differ in how the sign bit is interpreted. y will be exactly x,
    > ALWAYS. If y was signed, on the other hand, the value could be
    > different (if and only if it was interpreted as negative, i.e. the
    > sign bit was set), but the binary content would be rigorously the
    > same. Even in the case that y were signed, (unsigned)y would be
    > exactly x. That's because since the binary content is not modified, a
    > conversion that in the end converts back to the original type will
    > mean exatcly the same thing.


    What you say is true for many (most) implementations, but it's not
    at all guaranteed by the language.

    Integer types can have padding bits and/or trap representations.
    signed and unsigned int, for example, might not necessarily be
    able to represent the same number of values; (signed) int might
    have two different representations for zero.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Mar 20, 2011
    #9
  10. pozz

    puppi Guest

    Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) ->

    On Mar 19, 11:14 pm, Keith Thompson <> wrote:
    > puppi <> writes:
    > > On Mar 18, 7:06 am, pozz <> wrote:
    > >> int x = <value>;
    > >> int y = (int)((unsigned)x);

    >
    > >> The value of y is the same of x for any starting value and C
    > >> implementation?

    >
    > >> unsigned int x = <value>;
    > >> unsigned int y = (unsigned)((int)x);

    >
    > >> And in this case?

    >
    > >> In other words, is there a risk to loose any value switching from
    > >> signed to unsigned and viceversa representation of integers?

    >
    > > No. There is no risk. Unsigned and signed integers are the same: they
    > > only differ in how the sign bit is interpreted. y will be exactly x,
    > > ALWAYS. If y was signed, on the other hand, the value could be
    > > different (if and only if it was interpreted as negative, i.e. the
    > > sign bit was set), but the binary content would be rigorously the
    > > same. Even in the case that y were signed, (unsigned)y would be
    > > exactly x. That's because since the binary content is not modified, a
    > > conversion that in the end converts back to the original type will
    > > mean exatcly the same thing.

    >
    > What you say is true for many (most) implementations, but it's not
    > at all guaranteed by the language.
    >
    > Integer types can have padding bits and/or trap representations.
    > signed and unsigned int, for example, might not necessarily be
    > able to represent the same number of values; (signed) int might
    > have two different representations for zero.
    >
    > --
    > Keith Thompson (The_Other_Keith)  <http://www.ghoti.net/~kst>
    > Nokia
    > "We must do something.  This is something.  Therefore, we must do this."
    >     -- Antony Jay and Jonathan Lynn, "Yes Minister"


    You're correct, of course. I was assuming that signed integers were
    represented in two complement's form. Is there any (major) current
    implementation that disagrees with that?
     
    puppi, Mar 20, 2011
    #10
  11. Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned): I'll loose something?

    puppi <> writes:
    > On Mar 19, 11:14 pm, Keith Thompson <> wrote:

    [...]
    >> What you say is true for many (most) implementations, but it's not
    >> at all guaranteed by the language.
    >>
    >> Integer types can have padding bits and/or trap representations.
    >> signed and unsigned int, for example, might not necessarily be
    >> able to represent the same number of values; (signed) int might
    >> have two different representations for zero.

    >
    > You're correct, of course. I was assuming that signed integers were
    > represented in two complement's form.


    You were also (implicitly) assuming that the most negative
    representable value isn't treated as a trap representation, and
    that unsigned-to-signed conversion for values exceeding INT_MAX
    works as expected (it's implementation-defined).

    > Is there any (majorm) current
    > implementation that disagrees with that?


    I don't believe there are any conforming *hosted* implementations
    that don't meet those assumptions. There tends to be more variation
    among freestanding implementations, but I don't know the details.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Mar 20, 2011
    #11
  12. Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) ->

    Ben Bacarisse <> wrote:
    > pozz <> writes:

    <snip>
    > > unsigned int x = <value>;
    > > unsigned int y = (unsigned)((int)x);

    >
    > Neither case is safe.  Both can involve an out-of-range
    > conversion from unsigned to int.


    More subtle is the case...

    unsigned short x = USHRT_MAX;
    unsigned short y = ++x;

    The second initialisor expression can overflow if USHRT_MAX <=
    INT_MAX. Since ++x is just shorthand for x = x + 1, the sub-
    expression x + 1 can overflow if x is promoted to int and not
    unsigned int. That can be true even if USHRT_MAX == UINT_MAX in
    the case where UINT_MAX == INT_MAX.

    --
    Peter
     
    Peter Nilsson, Mar 20, 2011
    #12
  13. pozz

    Tim Rentsch Guest

    Re: (int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned): I'll loose something?

    Peter Nilsson <> writes:

    > Ben Bacarisse <> wrote:
    >> pozz <> writes:

    > <snip>
    >> > unsigned int x = <value>;
    >> > unsigned int y = (unsigned)((int)x);

    >>
    >> Neither case is safe. Both can involve an out-of-range
    >> conversion from unsigned to int.

    >
    > More subtle is the case...
    >
    > unsigned short x = USHRT_MAX;
    > unsigned short y = ++x;
    >
    > The second initialisor expression can overflow if USHRT_MAX <=
    > INT_MAX. [snip elaboration]


    Presumably you mean ++x can overflow if USHRT_MAX == INT_MAX.
    There is no overflow if USHRT_MAX < INT_MAX.
     
    Tim Rentsch, Mar 20, 2011
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Timo Freiberger
    Replies:
    3
    Views:
    952
    Bob Hairgrove
    Oct 30, 2004
  2. Schnoffos
    Replies:
    2
    Views:
    1,220
    Martien Verbruggen
    Jun 27, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,646
    Old Wolf
    Jan 20, 2004
  4. er
    Replies:
    6
    Views:
    491
    Andre Kostur
    Sep 14, 2007
  5. ciccio

    int*unsigned int = unsigned?

    ciccio, Jun 4, 2010, in forum: C++
    Replies:
    2
    Views:
    413
    Öö Tiib
    Jun 4, 2010
Loading...

Share This Page