Strange behaviour of long long and unsigned int

Discussion in 'C Programming' started by luke, Mar 8, 2006.

  1. luke

    luke Guest

    Hi everybody,
    please, can someone explain me this behaviour.

    I have the following piece of code:

    long long ll;
    unsigned int i = 2;
    ll = -1 * i;
    printf("%lld\n", ll);

    Why this prints 4294967294 instead of -2?
    Thanks in advance
    Luke
     
    luke, Mar 8, 2006
    #1
    1. Advertising

  2. luke

    Gowtham Guest

    Just type cast -1 to long long.

    ll = (long long)-1 * i;

    Thats it.
     
    Gowtham, Mar 8, 2006
    #2
    1. Advertising

  3. luke

    Grumble Guest

    luke wrote:
    > Hi everybody,
    > please, can someone explain me this behaviour.
    >
    > I have the following piece of code:
    >
    > long long ll;
    > unsigned int i = 2;
    > ll = -1 * i;
    > printf("%lld\n", ll);
    >
    > Why this prints 4294967294 instead of -2?


    http://c-faq.com/expr/intoverflow1.html
     
    Grumble, Mar 8, 2006
    #3
  4. "luke" <> writes:
    > I have the following piece of code:
    >
    > long long ll;
    > unsigned int i = 2;
    > ll = -1 * i;
    > printf("%lld\n", ll);
    >
    > Why this prints 4294967294 instead of -2?


    In
    ll = -1 * i;
    the expression -1 is of type int, and i is of type unsigned int, so
    the -1 is converted to unsigned int before the multiplication.
    Converting -1 to unsigned int yields UINT_MAX, which happens to be
    4294967295 in your implementation. Multiplying 4294967295 by 2 wraps
    around (because it's unsigned arithmetic), yielding 4294967294.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Mar 8, 2006
    #4
  5. luke

    luke Guest

    Thanks.
    Where can I find the rules for arithmetic conversions?
    I found this rules (taken from an ANSI C manual):

    "First, if the corresponding real type of either operand is long
    double, the other
    operand is converted, without change of type domain, to a type whose
    corresponding real type is long double.
    Otherwise, if the corresponding real type of either operand is double,
    the other
    operand is converted, without change of type domain, to a type whose
    corresponding real type is double.
    Otherwise, if the corresponding real type of either operand is float,
    the other
    operand is converted, without change of type domain, to a type whose
    corresponding real type is float.
    Otherwise, the integer promotions are performed on both operands. Then
    the
    following rules are applied to the promoted operands:
    If both operands have the same type, then no further conversion is
    needed.
    Otherwise, if both operands have signed integer types or both have
    unsigned
    integer types, the operand with the type of lesser integer conversion
    rank is
    converted to the type of the operand with greater rank.
    Otherwise, if the operand that has unsigned integer type has rank
    greater or
    equal to the rank of the type of the other operand, then the operand
    with
    signed integer type is converted to the type of the operand with
    unsigned
    integer type.
    Otherwise, if the type of the operand with signed integer type can
    represent
    all of the values of the type of the operand with unsigned integer
    type, then
    the operand with unsigned integer type is converted to the type of the
    operand with signed integer type.
    Otherwise, both operands are converted to the unsigned integer type
    corresponding to the type of the operand with signed integer type."

    Are this rules good or maybe can you suggest anything better?
    Thanks



    Keith Thompson wrote:

    > "luke" <> writes:
    > > I have the following piece of code:
    > >
    > > long long ll;
    > > unsigned int i = 2;
    > > ll = -1 * i;
    > > printf("%lld\n", ll);
    > >
    > > Why this prints 4294967294 instead of -2?

    >
    > In
    > ll = -1 * i;
    > the expression -1 is of type int, and i is of type unsigned int, so
    > the -1 is converted to unsigned int before the multiplication.
    > Converting -1 to unsigned int yields UINT_MAX, which happens to be
    > 4294967295 in your implementation. Multiplying 4294967295 by 2 wraps
    > around (because it's unsigned arithmetic), yielding 4294967294.
     
    luke, Mar 8, 2006
    #5
  6. luke

    Thad Smith Guest

    luke wrote:
    > Thanks.
    > Where can I find the rules for arithmetic conversions?


    The ISO (and ANSI) C Standard.

    > I found this rules (taken from an ANSI C manual):
    >
    > "First, if the corresponding real type of either operand is long
    > double, the other

    ....

    > Are this rules good or maybe can you suggest anything better?


    They are correct and useful, assuming you understand what is meant by
    integer rank.

    --
    Thad
     
    Thad Smith, Mar 9, 2006
    #6
  7. luke

    luke Guest

    Mmmh, I think rank is what is returned by sizeof() but I'm not sure
    about this.
    Can you explain me what rank really means?
    Thanks
    Luke

    Thad Smith wrote:

    > luke wrote:
    > > Thanks.
    > > Where can I find the rules for arithmetic conversions?

    >
    > The ISO (and ANSI) C Standard.
    >
    > > I found this rules (taken from an ANSI C manual):
    > >
    > > "First, if the corresponding real type of either operand is long
    > > double, the other

    > ...
    >
    > > Are this rules good or maybe can you suggest anything better?

    >
    > They are correct and useful, assuming you understand what is meant by
    > integer rank.
    >
    > --
    > Thad
     
    luke, Mar 9, 2006
    #7
  8. luke

    luke Guest

    In another ANSI C manual I found the following rules, which are
    different from the previous ones.
    Which one are good then??

    1.

    If either operand is long double, the other operand is converted
    to long double.
    2.

    If either operand is double, the other operand is converted to
    double.
    3.

    If either operand is float, the other operand is converted to
    float.
    4.

    Integral promotions are performed on both operands, and then the
    rules listed below are followed. These rules are a strict extension of
    the ANSI "Usual Arithmetic Conversions" rule (Section 3.2.1.5). This
    extension ensures that integral expressions will involve long long only
    if one of the operands is of type long long. For ANSI conforming
    compilation, the integral promotion rule is as defined in Section
    3.2.1.1 of the Standard. For non-ANSI compilation, the unsigned
    preserving promotion rule is used.
    1.

    If either operand is unsigned long long, the other operand
    is converted to unsigned long long,
    2.

    otherwise, if one operand is long long, the other operand
    is converted to long long,
    3.

    otherwise, if either operand is unsigned long int, the
    other operand is converted to unsigned long int,
    4.

    otherwise, if one operand is long int, and the other is
    unsigned
    int, and long int can represent all the values of an
    unsigned
    int, then the unsigned int is converted to a long int. (If
    one operand is long int, and the other is unsigned int, and long int
    can NOT represent all the values of an unsigned int, then both operands
    are converted to unsigned long int.)
    5.

    If either operand is long int, the other operand is
    converted to long int.
    6.

    If either operand is unsigned int, the other operand is
    converted to unsigned int.
    7.

    Otherwise, both operands have type int.
    Regards



    Thad Smith wrote:

    > > Are this rules good or maybe can you suggest anything better?

    >
    > They are correct and useful, assuming you understand what is meant by
    > integer rank.
    >
    > --
    > Thad
     
    luke, Mar 9, 2006
    #8
  9. luke

    Richard Bos Guest

    "luke" <> wrote:

    [ Please do not top-post. Please do snip. Thank you. ]

    > Mmmh, I think rank is what is returned by sizeof() but I'm not sure
    > about this.


    No, but it's a related concept. sizeof returns the actual storage size
    any type or object takes in bytes of memory; rank is a (relative, and
    non-measurable) indicator of the ideal mathematical size of an integer
    type.

    > Can you explain me what rank really means?


    It is defined precisely in paragraph 6.3.1.1 of the Standard, but
    basically, it's an indicator - not even a number - of how "large" a type
    is, in the sense of what it can and must be able to contain. For
    example:
    - a signed type and its corresponding unsigned type have the same rank
    - no signed integer types have the same rank, even if they look the same
    in all respects
    - a signed type which can hold larger numbers has higher rank than one
    which can hold smaller numbers
    - even if, say, INT_MAX == LONG_MAX, the rank of long is higher than
    that of int, and similar for the other default types
    - _Bool has the lowest rank of all
    and so on.

    The significance of this rank is that when integer types need to be
    compared to one another, types with lower rank are generally converted
    to types with higher rank.

    Richard
     
    Richard Bos, Mar 9, 2006
    #9
  10. Groovy hepcat luke was jivin' on 9 Mar 2006 01:49:02 -0800 in
    comp.lang.c.
    Re: Strange behaviour of long long and unsigned int's a cool scene!
    Dig it!

    >In another ANSI C manual I found the following rules, which are
    >different from the previous ones.


    No they're not. They're the same. They're just stated differently.
    They amount to the same thing.

    >Which one are good then??


    Both. But the set of rules you've quoted here (which I've snipped)
    lacks a rule for when both operands have the same type. But otherwise
    it's fine.

    --

    Dig the even newer still, yet more improved, sig!

    http://alphalink.com.au/~phaywood/
    "Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
    I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
     
    Peter Shaggy Haywood, Mar 12, 2006
    #10
    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:
    956
    Bob Hairgrove
    Oct 30, 2004
  2. George Marsaglia

    Assigning unsigned long to unsigned long long

    George Marsaglia, Jul 8, 2003, in forum: C Programming
    Replies:
    1
    Views:
    686
    Eric Sosman
    Jul 8, 2003
  3. Daniel Rudy

    unsigned long long int to long double

    Daniel Rudy, Sep 19, 2005, in forum: C Programming
    Replies:
    5
    Views:
    1,201
    Peter Shaggy Haywood
    Sep 20, 2005
  4. pereges

    Promoting unsigned long int to long int

    pereges, Jun 30, 2008, in forum: C Programming
    Replies:
    112
    Views:
    2,091
    David Thompson
    Jul 28, 2008
  5. pozz
    Replies:
    12
    Views:
    747
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page