'Unsigned decimal'

Discussion in 'C Programming' started by BartC, Nov 2, 2012.

  1. BartC

    BartC Guest

    I have this code:

    int a = -2147483648;
    long long int b = 2147483648;

    And gcc gives me this warning for each:

    "warning: this decimal constant is unsigned only in ISO C90"

    These types are signed 32 and 64 bits respectively. How to get rid of this
    warning? What is it's problem anyway, in the second example?

    (For the first, I guess that 2147483648 is out of range before the negation
    is applied.)

    --
    Bartc
    BartC, Nov 2, 2012
    #1
    1. Advertising

  2. BartC

    Les Cargill Guest

    BartC wrote:
    > I have this code:
    >
    > int a = -2147483648;
    > long long int b = 2147483648;
    >
    > And gcc gives me this warning for each:
    >
    > "warning: this decimal constant is unsigned only in ISO C90"
    >
    > These types are signed 32 and 64 bits respectively. How to get rid of
    > this warning? What is it's problem anyway, in the second example?
    >
    > (For the first, I guess that 2147483648 is out of range before the
    > negation is applied.)
    >


    Nope. -2147483648 is a perfectly valid ( although somewhat
    ambiguous ) 32 bit value ( assuming long is 32 bits for
    what you are doing ). It is 0x8000000. So is 2147483648.

    0x80000000 is never ambiguous.

    I would use hex:

    C:\c\usenet>cat long.c

    //signed long int a = (signed int)-2147483648L;
    //signed long long int b = (signed int)2147483648LL;

    signed long int a = 0x80000000L;
    signed long long int b = 0x80000000LL;
    int main(void)
    {


    printf("a=%ld\n",a);
    printf("b=%lld\n",b);

    printf("a=%08lx\n",a);
    printf("b=%08llx\n",b);
    return 0;
    }

    Output:

    C:\c\usenet>a
    a=-2147483648
    b=2147483648
    a=80000000
    b=80000000

    --
    Les Cargill
    Les Cargill, Nov 2, 2012
    #2
    1. Advertising

  3. BartC

    Ben Pfaff Guest

    "BartC" <> writes:

    > I have this code:
    >
    > int a = -2147483648;
    > long long int b = 2147483648;
    >
    > And gcc gives me this warning for each:
    >
    > "warning: this decimal constant is unsigned only in ISO C90"
    >
    > These types are signed 32 and 64 bits respectively. How to get rid of
    > this warning? What is it's problem anyway, in the second example?


    One approach is to write:

    int a = -2147483647 - 1;
    long long int b = 2147483648LL;
    Ben Pfaff, Nov 2, 2012
    #3
  4. BartC

    James Kuyper Guest

    On 11/02/2012 01:34 PM, BartC wrote:
    > I have this code:
    >
    > int a = -2147483648;
    > long long int b = 2147483648;
    >
    > And gcc gives me this warning for each:
    >
    > "warning: this decimal constant is unsigned only in ISO C90"
    >
    > These types are signed 32 and 64 bits respectively. How to get rid of this
    > warning? What is it's problem anyway, in the second example?


    I suspect you're using a system where INT_MAX==LONG_MAX==214783647;
    that's the case on my system, and I can reproduce your warning message
    when compiling for C90. According to the C99 rules, if 214783648 >
    LONG_MAX, then 214783648 has the type long long int. In C90, that was
    not an option, so I would guess that 214783648 had the type 'unsigned int'.
    Because unary minus is a operator, and not part of the integer literal
    syntax, you can't actually express INT_MIN as integer literal of type
    'int', when 'int' is a 2's complement type. The closest you can come is
    (-21478367-1).

    In the second case, it's simpler. Just apply the LL suffix to force
    interpretation as a long long integer literal.
    James Kuyper, Nov 2, 2012
    #4
  5. BartC

    James Kuyper Guest

    On 11/02/2012 01:49 PM, Les Cargill wrote:
    > BartC wrote:
    >> I have this code:
    >>
    >> int a = -2147483648;
    >> long long int b = 2147483648;
    >>
    >> And gcc gives me this warning for each:
    >>
    >> "warning: this decimal constant is unsigned only in ISO C90"
    >>
    >> These types are signed 32 and 64 bits respectively. How to get rid of
    >> this warning? What is it's problem anyway, in the second example?
    >>
    >> (For the first, I guess that 2147483648 is out of range before the
    >> negation is applied.)
    >>

    >
    > Nope. -2147483648 is a perfectly valid ( although somewhat
    > ambiguous ) 32 bit value ( assuming long is 32 bits for
    > what you are doing ). It is 0x8000000. So is 2147483648.


    In C90, you'd be correct - which just means that it's out of range for
    'int' both before, and after, the unary minus is evaluated.

    In C99 or later, it has type long long, which he's told us is a 64-bit
    type on his system.
    James Kuyper, Nov 2, 2012
    #5
  6. Les Cargill <> writes:
    > BartC wrote:
    >> I have this code:
    >>
    >> int a = -2147483648;
    >> long long int b = 2147483648;
    >>
    >> And gcc gives me this warning for each:
    >>
    >> "warning: this decimal constant is unsigned only in ISO C90"
    >>
    >> These types are signed 32 and 64 bits respectively. How to get rid of
    >> this warning? What is it's problem anyway, in the second example?
    >>
    >> (For the first, I guess that 2147483648 is out of range before the
    >> negation is applied.)
    >>

    >
    > Nope. -2147483648 is a perfectly valid ( although somewhat
    > ambiguous ) 32 bit value ( assuming long is 32 bits for
    > what you are doing ). It is 0x8000000. So is 2147483648.
    >
    > 0x80000000 is never ambiguous.


    Not quite.

    In C99 and later, a decimal constant's type is the first of:

    int, long int, long long int

    in which it fits. In C90 (before long long was invented), the
    sequence takes a left turn into unsigned land:

    int, long int, unsigned long int

    -2147483648 is not a constant; it's a constant expression consisting
    of a unary "-" applied to the contant 2147483648.

    Assuming int and long are 32 bits and long long is 64 bits (if it
    exists), in C90 the constant 2147483648 is of type unsigned long.
    Applying unary "-" to it yields an unsigned long result with
    the same value. Initializing the int object "a" with that value
    causes it to be converted from unsigned long to (signed) int --
    which, since 2147483648L is outside the range of int, yields an
    implementation-defined value. That value is very likely to be
    -2147483648, which is what was intended.

    In C99 and later the constant 2147483648 is of type long long, since
    it won't fit in a long. Applying unary "-" gives you an expression
    of type long long with the value -2147483648. Converting that
    value to int unambiguously yields the int value -2147483648.

    So as of C99, the declaration

    int a = -2147483648;

    is unambiguous and initializes a to the obvious value; in C90, it
    *probably* does so.

    The rules for octal and hexadecimal constants are a bit different. In
    C90, the sequence is:

    int, unsigned int, long int, unsigned long int

    and in C99 and later, its:

    int, unsigned int, long int, unsigned long int, long long int,
    unsigned long long int

    So changing the declaration to:

    int a = -0x80000000

    doesn't help for C90 (though it may remove the warning); the constant
    is of type unsigned int, and the conversion is implementation-defined
    (but very likely to yield the result you want). And in C99 and
    later, it actually introduces an ambiguity, since -0x80000000 is of
    type unsigned int, whereas -2147483648 is of type (signed) long long.

    The warning, I think, refers just to the constant 2147483648,
    without regard to its context.

    If you're willing to assume that int is 32 bits (more specifically,
    that INT_MIN == -2147483648 (mathematically)), then you can just
    write:

    int a = INT_MIN;

    If not, you can write:

    int a = -2147483647-1;

    to avoid the warning.

    For the second declaration, you could write:

    long long int b = 2147483647+1;

    or

    long long int b = 2147483648LL;

    If you can't assume that int is at least 32 bits, things could
    get a bit more complicated; there's no guarantee that the value
    -2147483648 can be stored in an int.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 2, 2012
    #6
  7. BartC

    Joe Pfeiffer Guest

    "BartC" <> writes:

    > I have this code:
    >
    > int a = -2147483648;
    > long long int b = 2147483648;
    >
    > And gcc gives me this warning for each:
    >
    > "warning: this decimal constant is unsigned only in ISO C90"
    >
    > These types are signed 32 and 64 bits respectively. How to get rid of
    > this warning? What is it's problem anyway, in the second example?
    >
    > (For the first, I guess that 2147483648 is out of range before the
    > negation is applied.)


    The variables you're declaring are int and long long int, but the
    constants are ints (note that the first one is a unary operator being
    applied to a constant -- it isn't a negative constant. In the standard,
    a decimal constant is just the digits, not the leading minus sign). The
    compiler is warning you that ints can't represent those constants; they
    have to be unsigned.

    If you replace them with

    int a = -2147483648u;
    long long int b = 2147483648u;

    (telling the compiler to make them unsigned)

    or

    int a = -2147483648ll;
    long long int b = 2147483648ll;

    (telling it you want them to be 64 bit)

    the warnings go away, and the initialization successfully converts them
    to what you had in mind.
    Joe Pfeiffer, Nov 2, 2012
    #7
  8. Joe Pfeiffer <> writes:
    > "BartC" <> writes:
    >> I have this code:
    >> int a = -2147483648;
    >> long long int b = 2147483648;
    >>
    >> And gcc gives me this warning for each:
    >>
    >> "warning: this decimal constant is unsigned only in ISO C90"
    >>
    >> These types are signed 32 and 64 bits respectively. How to get rid of
    >> this warning? What is it's problem anyway, in the second example?
    >>
    >> (For the first, I guess that 2147483648 is out of range before the
    >> negation is applied.)

    >
    > The variables you're declaring are int and long long int, but the
    > constants are ints (note that the first one is a unary operator being
    > applied to a constant -- it isn't a negative constant. In the standard,
    > a decimal constant is just the digits, not the leading minus sign). The
    > compiler is warning you that ints can't represent those constants; they
    > have to be unsigned.


    Given INT_MAX==2147483647 and LONG_MAX==2147483647, 2147483648
    cannot be of type int. It's of type unsigned long in C90, signed
    long long in C99 and up. See my other followup for details.

    > If you replace them with
    >
    > int a = -2147483648u;
    > long long int b = 2147483648u;
    >
    > (telling the compiler to make them unsigned)
    >
    > or
    >
    > int a = -2147483648ll;
    > long long int b = 2147483648ll;
    >
    > (telling it you want them to be 64 bit)
    >
    > the warnings go away, and the initialization successfully converts them
    > to what you had in mind.


    Adding a "u" suffix may inhibit the warning, but it won't
    fix the problem that the unsigned-to-signed conversion has an
    implementation-defined result. The "LL" suffix (don't use "ll", it
    looks too much like "11") guarantees that the constant is signed, and
    makes the conversion well defined (assuming int is at least 32 bits).
    It kills portability to pre-C99 compilers; that may not be an issue.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 2, 2012
    #8
  9. BartC

    BartC Guest

    "BartC" <> wrote in message news:k7108j$1t4$...

    > int a = -2147483648;
    > long long int b = 2147483648;
    >
    > And gcc gives me this warning for each:
    >
    > "warning: this decimal constant is unsigned only in ISO C90"


    Thanks for the replies. I've replaced instances of -2147483648 with
    0x80000000 where an int is expected. And using an LL suffix for any long
    long ints.

    That's shut the compiler up for now. (These numbers occur in data
    initialisation lists written by external software; the ints have to be
    specially detected so as to generate the alternate form. Doubtless the same
    problem will crop up elsewhere and will need fixing too. Odd that I can't
    just write a legal int value, 0x80000000, in decimal!)

    (I would have used the -cstd=C99 option in gcc if it had helped, but I tried
    to use that yesterday to provide designated initialisers for one of my
    complex structs, but it didn't like the 3-deep unnamed unions and structs
    that it uses. Since I need that struct as it is, I think that C99 is out!)

    --
    Bartc
    BartC, Nov 2, 2012
    #9
  10. "BartC" <> writes:
    > "BartC" <> wrote in message news:k7108j$1t4$...
    >> int a = -2147483648;
    >> long long int b = 2147483648;
    >>
    >> And gcc gives me this warning for each:
    >>
    >> "warning: this decimal constant is unsigned only in ISO C90"

    >
    > Thanks for the replies. I've replaced instances of -2147483648 with
    > 0x80000000 where an int is expected. And using an LL suffix for any long
    > long ints.


    That eliminates the warning (because 0x8000000 is of type
    unsigned int in both C90 and C99), but you're still doing an
    implementation-defined conversion from unsigned to signed.
    It's *probably* safe to assume that 0x80000000 converts to
    (int)-2147483648; you'll have to decide whether that's good enough.

    Using 2147483648LL should eliminate both the warning and the
    implementation-definedness of the conversion -- if you can assume
    support for the LL suffix.

    > That's shut the compiler up for now. (These numbers occur in data
    > initialisation lists written by external software; the ints have to be
    > specially detected so as to generate the alternate form. Doubtless the same
    > problem will crop up elsewhere and will need fixing too. Odd that I can't
    > just write a legal int value, 0x80000000, in decimal!)


    Because 0x8000000 isn't a legal int value; INT_MAX on your system is
    0x7FFFFFFF.

    > (I would have used the -cstd=C99 option in gcc if it had helped, but I tried
    > to use that yesterday to provide designated initialisers for one of my
    > complex structs, but it didn't like the 3-deep unnamed unions and structs
    > that it uses. Since I need that struct as it is, I think that C99 is out!)


    C11 supports unnamed unions and structs. Depending on how
    recent your gcc is, you can probably use "-std=c11 -pedantic" or
    "-std=c1x -pedantic". (With "-std=c99" but without "-pedantic", gcc
    doesn't complain about unnamed unions and structs.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 2, 2012
    #10
  11. BartC

    Eric Sosman Guest

    On 11/2/2012 5:03 PM, BartC wrote:
    >
    >
    > "BartC" <> wrote in message news:k7108j$1t4$...
    >
    >> int a = -2147483648;
    >> long long int b = 2147483648;
    >>
    >> And gcc gives me this warning for each:
    >>
    >> "warning: this decimal constant is unsigned only in ISO C90"

    >
    > Thanks for the replies. I've replaced instances of -2147483648 with
    > 0x80000000 where an int is expected. And using an LL suffix for any long
    > long ints.
    >
    > That's shut the compiler up for now. (These numbers occur in data
    > initialisation lists written by external software; the ints have to be
    > specially detected so as to generate the alternate form. Doubtless the same
    > problem will crop up elsewhere and will need fixing too. Odd that I can't
    > just write a legal int value, 0x80000000, in decimal!)


    Others have explained this, but the explanation doesn't seem
    to have penetrated. Allow me to try again: From what you say, on
    your system `int' has 32 significant bits, one of which is the
    sign bit. Assuming no pad bits, INT_MAX is then 0x7fffffff. The
    value 0x8000000 is

    one greater than 0x7fffffff, hence

    one greater than INT_MAX, hence

    *not* "a legal int value."

    Observing that 0x7fffffff is equal to 2147483647, we can also
    reason that the value 2147483648 is

    one greater than 2147483647, hence

    one greater than INT_MAX, hence

    *not* "a legal int value."

    For your system's `int's, 0x80000000 and 2147483648 are out of
    range, beyond the pale, in an alternate universe, in your dreams,
    and pining for the fjords.

    --
    Eric Sosman
    d
    Eric Sosman, Nov 2, 2012
    #11
  12. BartC

    James Kuyper Guest

    On 11/02/2012 05:03 PM, BartC wrote:
    >
    >
    > "BartC" <> wrote in message news:k7108j$1t4$...
    >
    >> int a = -2147483648;
    >> long long int b = 2147483648;
    >>
    >> And gcc gives me this warning for each:
    >>
    >> "warning: this decimal constant is unsigned only in ISO C90"

    >
    > Thanks for the replies. I've replaced instances of -2147483648 with
    > 0x80000000 where an int is expected. And using an LL suffix for any long
    > long ints.
    >
    > That's shut the compiler up for now. (These numbers occur in data
    > initialisation lists written by external software; the ints have to be
    > specially detected so as to generate the alternate form. Doubtless the same
    > problem will crop up elsewhere and will need fixing too. Odd that I can't
    > just write a legal int value, 0x80000000, in decimal!)


    The fact that you can't write INT_MIN as an integer constant is due to
    two things. First, integer constants cannot be negative: -9 is not a
    negative integer constant, it's a unary minus expression whose operand
    is an integer constant of 9. Personally, I don't think that was a good
    idea. I'm not sure whether there's any code that would be broken if it
    were changed; if not, I'd favor changing it.

    Secondly, because 'int' has a 2's complement representation on your
    system, INT_MAX + INT_MIN == -1. As a result, INT_MIN cannot be written
    as -x for any x which is a constant of 'int' type.

    Note that on your machine, 0x80000000 is not such a legal int value,
    because it's value is greater than INT_MAX, and it's type is therefore
    actually unsigned int. The fact that it converts to an int value of
    -21474783648 is not guaranteed by the standard, not even on systems
    where that is in fact the value of INT_MIN. Is there some reason you
    can't use INT_MIN - for instance, you need your code to continue working
    unchanged even if INT_MIN < -21474783648? In that case, I'd strongly
    recommend using (-21474783647-1), which is the conventional work-around
    for this long-standing problem.
    James Kuyper, Nov 2, 2012
    #12
  13. BartC

    BartC Guest

    "James Kuyper" <> wrote in message
    news:...
    > On 11/02/2012 05:03 PM, BartC wrote:


    >> I've replaced instances of -2147483648 with
    >> 0x80000000 where an int is expected.


    > In that case, I'd strongly
    > recommend using (-21474783647-1), which is the conventional work-around
    > for this long-standing problem.


    OK, will do. I used 0x80000000h because it was easier to type, and did an
    equally good job of eliminating the warning. (And someone suggested using
    it.)

    --
    Bartc
    BartC, Nov 2, 2012
    #13
  14. BartC

    Ben Pfaff Guest

    "BartC" <> writes:

    > "James Kuyper" <> wrote in message
    > news:...
    >> On 11/02/2012 05:03 PM, BartC wrote:

    >
    >>> I've replaced instances of -2147483648 with
    >>> 0x80000000 where an int is expected.

    >
    >> In that case, I'd strongly
    >> recommend using (-21474783647-1), which is the conventional work-around
    >> for this long-standing problem.

    >
    > OK, will do. I used 0x80000000h because it was easier to type, and did
    > an equally good job of eliminating the warning. (And someone suggested
    > using it.)


    Did you really include the "h" suffix?
    Ben Pfaff, Nov 2, 2012
    #14
  15. BartC

    BartC Guest

    "Ben Pfaff" <> wrote in message
    news:...
    > "BartC" <> writes:


    >> OK, will do. I used 0x80000000h because it was easier to type, and did
    >> an equally good job of eliminating the warning. (And someone suggested
    >> using it.)

    >
    > Did you really include the "h" suffix?


    Don't think so; gcc would have complained. (The language used to generate
    the C uses -h instead of 0x-. It must have slipped in above while I was
    concentrating on getting the right number of zeros.)

    --
    Bartc
    BartC, Nov 2, 2012
    #15
  16. BartC

    Les Cargill Guest

    James Kuyper wrote:
    > On 11/02/2012 01:49 PM, Les Cargill wrote:
    >> BartC wrote:
    >>> I have this code:
    >>>
    >>> int a = -2147483648;
    >>> long long int b = 2147483648;
    >>>
    >>> And gcc gives me this warning for each:
    >>>
    >>> "warning: this decimal constant is unsigned only in ISO C90"
    >>>
    >>> These types are signed 32 and 64 bits respectively. How to get rid of
    >>> this warning? What is it's problem anyway, in the second example?
    >>>
    >>> (For the first, I guess that 2147483648 is out of range before the
    >>> negation is applied.)
    >>>

    >>
    >> Nope. -2147483648 is a perfectly valid ( although somewhat
    >> ambiguous ) 32 bit value ( assuming long is 32 bits for
    >> what you are doing ). It is 0x8000000. So is 2147483648.

    >
    > In C90, you'd be correct - which just means that it's out of range for
    > 'int' both before, and after, the unary minus is evaluated.
    >


    In all fairness, every time I ever tested this, the implementation
    did what was codified in the C90 spec. I have by long habit used
    hexadecimal notation for anything that's remotely close
    to this problem.

    > In C99 or later, it has type long long, which he's told us is a 64-bit
    > type on his system.
    >



    Oh, sorry I neglected that.

    --
    Les Cargill
    Les Cargill, Nov 3, 2012
    #16
  17. BartC

    Les Cargill Guest

    Keith Thompson wrote:
    > "BartC" <> writes:
    >> "BartC" <> wrote in message news:k7108j$1t4$...
    >>> int a = -2147483648;
    >>> long long int b = 2147483648;
    >>>
    >>> And gcc gives me this warning for each:
    >>>
    >>> "warning: this decimal constant is unsigned only in ISO C90"

    >>
    >> Thanks for the replies. I've replaced instances of -2147483648 with
    >> 0x80000000 where an int is expected. And using an LL suffix for any long
    >> long ints.

    >
    > That eliminates the warning (because 0x8000000 is of type
    > unsigned int in both C90 and C99), but you're still doing an
    > implementation-defined conversion from unsigned to signed.
    > It's *probably* safe to assume that 0x80000000 converts to
    > (int)-2147483648; you'll have to decide whether that's good enough.
    >
    > Using 2147483648LL should eliminate both the warning and the
    > implementation-definedness of the conversion -- if you can assume
    > support for the LL suffix.
    >


    In my own defense :), I tried that and it failed.
    C:\c\usenet>gcc -v
    Reading specs from c:/Mingw/bin/../lib/gcc/mingw32/3.4.5/specs
    Configured with: ../gcc-3.4.5-20060117-3/configure --with-gcc
    --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32
    --prefix=/mingw --enable-threads --disable-nls
    --enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry
    --disable-shared --
    enable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x
    --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter
    --enable-hash-synchronization --enable-libstdcxx-debug
    Thread model: win32
    gcc version 3.4.5 (mingw-vista special r3)

    >> That's shut the compiler up for now. (These numbers occur in data
    >> initialisation lists written by external software; the ints have to be
    >> specially detected so as to generate the alternate form. Doubtless the same
    >> problem will crop up elsewhere and will need fixing too. Odd that I can't
    >> just write a legal int value, 0x80000000, in decimal!)

    >
    > Because 0x8000000 isn't a legal int value; INT_MAX on your system is
    > 0x7FFFFFFF.
    >


    But let us be clear - 0x8000000 is not a legal value because it
    maps to both numbers. There is no bijective map from 0x8000000
    to the decimal representations - hence my "ambiguous".

    The point I was trying to make is that hex notation is a strategy to
    use when the other conventions break down. But as you note,
    "you gotta know the territory."

    <snip>

    --
    Les Cargill
    Les Cargill, Nov 3, 2012
    #17
  18. BartC

    Les Cargill Guest

    BartC wrote:
    > "James Kuyper" <> wrote in message
    > news:...
    >> On 11/02/2012 05:03 PM, BartC wrote:

    >
    >>> I've replaced instances of -2147483648 with
    >>> 0x80000000 where an int is expected.

    >
    >> In that case, I'd strongly
    >> recommend using (-21474783647-1), which is the conventional work-around
    >> for this long-standing problem.

    >
    > OK, will do. I used 0x80000000h because it was easier to type, and did
    > an equally good job of eliminating the warning. (And someone suggested
    > using it.)
    >


    I suggested using it as something more like a heuristic, not
    as a polished piece of Language Law. Indeed, the point I
    was making was that there were two different decimal numbers
    that map to 0x80000000.

    For the case where long is 32 bits and long long is 64,
    for the vast majority of implementations, it will work
    *just fine*, but you really have to verify it and not trust it.
    This is One Of Those Numbers.

    Perhaps it has less value than I would prefer, but what I
    put up is closer to what I'd have done in this case. What
    the others have done is a detailed analysis, which is many
    times more information dense than what I'd provided.

    it's a matter of how deeply you need to drill.

    --
    Les Cargill
    Les Cargill, Nov 3, 2012
    #18
  19. Les Cargill <> writes:
    > Keith Thompson wrote:
    >> "BartC" <> writes:
    >>> "BartC" <> wrote in message news:k7108j$1t4$...
    >>>> int a = -2147483648;
    >>>> long long int b = 2147483648;
    >>>>
    >>>> And gcc gives me this warning for each:
    >>>>
    >>>> "warning: this decimal constant is unsigned only in ISO C90"
    >>>
    >>> Thanks for the replies. I've replaced instances of -2147483648 with
    >>> 0x80000000 where an int is expected. And using an LL suffix for any long
    >>> long ints.

    >>
    >> That eliminates the warning (because 0x8000000 is of type
    >> unsigned int in both C90 and C99), but you're still doing an
    >> implementation-defined conversion from unsigned to signed.
    >> It's *probably* safe to assume that 0x80000000 converts to
    >> (int)-2147483648; you'll have to decide whether that's good enough.
    >>
    >> Using 2147483648LL should eliminate both the warning and the
    >> implementation-definedness of the conversion -- if you can assume
    >> support for the LL suffix.

    >
    > In my own defense :), I tried that and it failed.
    > C:\c\usenet>gcc -v

    [snip]
    > gcc version 3.4.5 (mingw-vista special r3)


    How did it fail?

    For me, this program:

    #include <stdio.h>
    int main(void) {
    int a = -2147483648LL;
    long long int b = 2147483648LL;
    printf("a = %d\n", a);
    printf("b = %lld\n", b);
    return 0;
    }

    compiles without warnings and produces this output:

    a = -2147483648
    b = 2147483648

    >>> That's shut the compiler up for now. (These numbers occur in data
    >>> initialisation lists written by external software; the ints have to be
    >>> specially detected so as to generate the alternate form. Doubtless the same
    >>> problem will crop up elsewhere and will need fixing too. Odd that I can't
    >>> just write a legal int value, 0x80000000, in decimal!)

    >>
    >> Because 0x8000000 isn't a legal int value; INT_MAX on your system is
    >> 0x7FFFFFFF.

    >
    > But let us be clear - 0x8000000 is not a legal value because it
    > maps to both numbers. There is no bijective map from 0x8000000
    > to the decimal representations - hence my "ambiguous".


    I'm not sure what you mean by "maps to both numbers". What numbers
    are you referring to?

    0x80000000 has a single mathematical value, namely 2,147,483,648.
    Its type depends on the ranges of the fundamental types for
    an implementation; it could be int, unsigned int, long int, or
    unsigned long int. (Conveniently, it's the same in C90 and C99.)
    It might map to different values if you convert it to some other
    type, but that's not what makes it "not a legal value".

    > The point I was trying to make is that hex notation is a strategy to
    > use when the other conventions break down. But as you note,
    > "you gotta know the territory."


    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 3, 2012
    #19
  20. BartC

    Les Cargill Guest

    Keith Thompson wrote:
    > Les Cargill <> writes:
    >> Keith Thompson wrote:
    >>> "BartC" <> writes:
    >>>> "BartC" <> wrote in message news:k7108j$1t4$...
    >>>>> int a = -2147483648;
    >>>>> long long int b = 2147483648;
    >>>>>
    >>>>> And gcc gives me this warning for each:
    >>>>>
    >>>>> "warning: this decimal constant is unsigned only in ISO C90"
    >>>>
    >>>> Thanks for the replies. I've replaced instances of -2147483648 with
    >>>> 0x80000000 where an int is expected. And using an LL suffix for any long
    >>>> long ints.
    >>>
    >>> That eliminates the warning (because 0x8000000 is of type
    >>> unsigned int in both C90 and C99), but you're still doing an
    >>> implementation-defined conversion from unsigned to signed.
    >>> It's *probably* safe to assume that 0x80000000 converts to
    >>> (int)-2147483648; you'll have to decide whether that's good enough.
    >>>
    >>> Using 2147483648LL should eliminate both the warning and the
    >>> implementation-definedness of the conversion -- if you can assume
    >>> support for the LL suffix.

    >>
    >> In my own defense :), I tried that and it failed.
    >> C:\c\usenet>gcc -v

    > [snip]
    >> gcc version 3.4.5 (mingw-vista special r3)

    >
    > How did it fail?
    >
    > For me, this program:
    >
    > #include <stdio.h>
    > int main(void) {
    > int a = -2147483648LL;
    > long long int b = 2147483648LL;
    > printf("a = %d\n", a);
    > printf("b = %lld\n", b);
    > return 0;
    > }
    >
    > compiles without warnings and produces this output:
    >
    > a = -2147483648
    > b = 2147483648
    >


    It warning-ed.

    C:\c\usenet>gcc -o long.exe long.c
    long.c:2: warning: this decimal constant is unsigned only in ISO C

    C:\c\usenet>cat long.c

    signed long int a = -2147483648L;
    signed long long int b = 2147483648LL;

    //signed long int a = 0x80000000L;
    //signed long long int b = 0x80000000LL;

    int main(void)
    {
    printf("a=%ld\n",a);
    printf("b=%lld\n",b);

    printf("a=%08lx\n",a);
    printf("b=%08llx\n",b);
    return 0;
    }

    C:\c\usenet>
    C:\c\usenet>
    C:\c\usenet>long.exe
    a=-2147483648
    b=2147483648
    a=80000000
    b=80000000

    C:\c\usenet>


    >>>> That's shut the compiler up for now. (These numbers occur in data
    >>>> initialisation lists written by external software; the ints have to be
    >>>> specially detected so as to generate the alternate form. Doubtless the same
    >>>> problem will crop up elsewhere and will need fixing too. Odd that I can't
    >>>> just write a legal int value, 0x80000000, in decimal!)
    >>>
    >>> Because 0x8000000 isn't a legal int value; INT_MAX on your system is
    >>> 0x7FFFFFFF.

    >>
    >> But let us be clear - 0x8000000 is not a legal value because it
    >> maps to both numbers. There is no bijective map from 0x8000000
    >> to the decimal representations - hence my "ambiguous".

    >
    > I'm not sure what you mean by "maps to both numbers". What numbers
    > are you referring to?
    >


    There are two strings embedded in the source code - -2147483648
    and 2147483648 - which map to the same hex value, for the right toolsets
    and declarations. As you note, -2147483648 is actually an expression,
    but it is still, SFAIK, a constant value.

    > 0x80000000 has a single mathematical value, namely 2,147,483,648.
    > Its type depends on the ranges of the fundamental types for
    > an implementation; it could be int, unsigned int, long int, or
    > unsigned long int. (Conveniently, it's the same in C90 and C99.)
    > It might map to different values if you convert it to some other
    > type, but that's not what makes it "not a legal value".
    >
    >> The point I was trying to make is that hex notation is a strategy to
    >> use when the other conventions break down. But as you note,
    >> "you gotta know the territory."

    >

    --
    Les Cargill
    Les Cargill, Nov 3, 2012
    #20
    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. Ven
    Replies:
    3
    Views:
    1,296
  2. Gilbert Fine
    Replies:
    8
    Views:
    880
    Zentrader
    Aug 1, 2007
  3. Vitaliy
    Replies:
    1
    Views:
    455
    Peter Otten
    May 29, 2008
  4. valpa
    Replies:
    11
    Views:
    1,480
    Steven D'Aprano
    Mar 24, 2009
  5. pozz
    Replies:
    12
    Views:
    704
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page