big decimal integer constant warning

Discussion in 'C Programming' started by fctk, Mar 29, 2006.

  1. fctk

    fctk Guest

    hello,

    i'm trying to compile this small program:

    int main(void) {

    unsigned long int max;

    max = 4000000000;

    return 0;

    }

    but i get the following warning, and can't understand why:

    limits.c: In function `main':
    limits.c:5: warning: this decimal constant is unsigned only in ISO C90

    i read both here
    (http://www-ccs.ucsd.edu/c/express.html#decimal integer constant)
    and on my book (Kelley-Pohl), that if i have a decimal integer constant
    with no suffix, then the compiler will choose among the following
    ordered list:

    1) int
    2) long int
    3) unsigned long int

    the first one which is able to represent that constant. since on my
    system both int and long int are 4 bytes sized, then i would expect
    4000000000 is unsigned long int. since i am assigning an unsigned long
    int constant to an unsigned long int variable, i don't see why i should
    get that warning.

    i know two ways to avoid the warning:

    1) specifing 4000000000UL instead of 4000000000
    2) using 0xEE6B2800 instead of 4000000000

    but i'd like to understand why 4000000000 is not ok.

    note that i'd like to write only ANSI/ISO C compatible programs
    (C89/C90), no traditional C or C99 ones (after having learned C89, i
    will switch to C99 if i'll have time).

    i am using gcc version 3.4.4 on a gentoo linux system.
    parameters: gcc -x c -ansi -pedantic -Wall -Wextra (i get that warning
    also with no parameters at all)

    also, i found this parameter:

    -Wtraditional

    [...]

    * The ISO type of an integer constant has a different width or
    signedness from its traditional type. This warning is only issued if
    the base of the constant is ten. I.e. hexadecimal or octal values,
    which typically represent bit patterns, are not warned about.

    [...]

    anyway, even if i put -Wno-traditional, i always get that warning.
     
    fctk, Mar 29, 2006
    #1
    1. Advertising

  2. fctk

    Eric Sosman Guest

    fctk wrote On 03/29/06 10:26,:
    > hello,
    >
    > i'm trying to compile this small program:
    >
    > int main(void) {
    >
    > unsigned long int max;
    >
    > max = 4000000000;
    >
    > return 0;
    >
    > }
    >
    > but i get the following warning, and can't understand why:
    >
    > limits.c: In function `main':
    > limits.c:5: warning: this decimal constant is unsigned only in ISO C90


    The compiler is warning you that the rules changed
    between C90 and C99, and that the type of the constant
    depends on which Standard you follow -- to put it another
    way, the type of the constant is "unstable" in the sense
    that it could change with a compiler upgrade.

    For C90, the rule is as you stated: the type will be
    the first of int, long int, or unsigned long int that
    can accommodate the value, and on your system this comes
    down to unsigned long int.

    For C99, the type will be the first of int, long int,
    or long long int that can accommodate the value, which
    for your system would turn out to be long long int.

    Recommendation: If you want an unsigned long, tack
    on a "UL" suffix.

    --
     
    Eric Sosman, Mar 29, 2006
    #2
    1. Advertising

  3. fctk

    Jack Klein Guest

    On Wed, 29 Mar 2006 17:26:08 +0200, fctk <-> wrote in comp.lang.c:

    > hello,
    >
    > i'm trying to compile this small program:
    >
    > int main(void) {
    >
    > unsigned long int max;
    >
    > max = 4000000000;
    >
    > return 0;
    >
    > }
    >
    > but i get the following warning, and can't understand why:
    >
    > limits.c: In function `main':
    > limits.c:5: warning: this decimal constant is unsigned only in ISO C90


    That's because the rules changed in 1999.

    > i read both here
    > (http://www-ccs.ucsd.edu/c/express.html#decimal integer constant)
    > and on my book (Kelley-Pohl), that if i have a decimal integer constant
    > with no suffix, then the compiler will choose among the following
    > ordered list:
    >
    > 1) int
    > 2) long int
    > 3) unsigned long int
    >
    > the first one which is able to represent that constant. since on my
    > system both int and long int are 4 bytes sized, then i would expect
    > 4000000000 is unsigned long int. since i am assigning an unsigned long
    > int constant to an unsigned long int variable, i don't see why i should
    > get that warning.


    That's because the rules changed in 1999. If your compiler uses the
    C99 rules, an unadorned decimal constant is the first one of:

    -- signed int
    -- signed long
    -- signed long long

    ....in which it fits. Under C99, an unadorned decimal constant never
    becomes an unsigned type.

    So the diagnostic is telling you that the constant is interpreted
    differently depending on which version of ISO C is being conformed to.
    If the compiler is invoked in C90 conforming mode, the type of the
    constant is "unsigned long", but in C99 conforming mode, the type is
    "signed long long". If the destination was a signed type, the actual
    value after initialization might be different between the two
    versions. And this code could break on other platforms.

    > i know two ways to avoid the warning:
    >
    > 1) specifing 4000000000UL instead of 4000000000
    > 2) using 0xEE6B2800 instead of 4000000000
    >
    > but i'd like to understand why 4000000000 is not ok.


    Nobody says that it isn't "OK". A compiler is allowed to issue a
    diagnostic about anything for any reason, as long as it issues those
    required by the standard.

    > note that i'd like to write only ANSI/ISO C compatible programs
    > (C89/C90), no traditional C or C99 ones (after having learned C89, i
    > will switch to C99 if i'll have time).


    Then follow the MISRA rule (one of the good ones) about always
    specifying a type for numeric literals.

    > i am using gcc version 3.4.4 on a gentoo linux system.
    > parameters: gcc -x c -ansi -pedantic -Wall -Wextra (i get that warning
    > also with no parameters at all)


    IIRC, 3.x versions of gcc had some C99 features included, and they,
    and even earlier versions, of gcc supported the "long long" int types
    as an extension to C90.

    > also, i found this parameter:
    >
    > -Wtraditional
    >
    > [...]
    >
    > * The ISO type of an integer constant has a different width or
    > signedness from its traditional type. This warning is only issued if
    > the base of the constant is ten. I.e. hexadecimal or octal values,
    > which typically represent bit patterns, are not warned about.
    >
    > [...]
    >
    > anyway, even if i put -Wno-traditional, i always get that warning.


    The real answer is "don't do this". Specify the exact type of your
    literal with a suffix, for maximum portability under any version of
    the C standard.

    Also consult your compiler documentation. There is some way to tell
    gcc which version of the C standard you want it to conform to.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Mar 29, 2006
    #3
  4. On 2006-03-29 10:26:08 -0500, fctk <-> said:

    > hello,
    >
    > i'm trying to compile this small program:
    >
    > int main(void) {
    >
    > unsigned long int max;
    >
    > max = 4000000000;
    >
    > return 0;
    >
    > }
    >
    > but i get the following warning, and can't understand why:
    >
    > limits.c: In function `main':
    > limits.c:5: warning: this decimal constant is unsigned only in ISO C90


    Because under C99, the type of the constant is "long long" (which is signed),
    while under C90 (assuming 4 byte ints and longs), it is "unsigned long" (which
    is unsigned). Hence, the warning is telling you that your constant is unsigned
    under C90, but not under C99, and that you may get different results when you
    change compilers.

    --
    Clark S. Cox, III
     
    Clark S. Cox III, Mar 29, 2006
    #4
  5. fctk

    Spoon Guest

    Spoon, Mar 30, 2006
    #5
  6. fctk

    fctk Guest

    Eric Sosman wrote:
    > The compiler is warning you that the rules changed
    > between C90 and C99, and that the type of the constant
    > depends on which Standard you follow -- to put it another
    > way, the type of the constant is "unstable" in the sense
    > that it could change with a compiler upgrade.


    Jack Klein wrote:
    > That's because the rules changed in 1999.


    Clark S. Cox III wrote:
    > Because under C99, the type of the constant is "long long" (which is signed),
    > while under C90 (assuming 4 byte ints and longs), it is "unsigned long" (which
    > is unsigned). Hence, the warning is telling you that your constant is unsigned
    > under C90, but not under C99, and that you may get different results when you
    > change compilers.


    ok, it seems you all agree on the reason of that warning.

    i tried to specify -std=iso9899:1990 (C89/C90) in the gcc parameters
    list, but i get that warning again.

    i still wonder. i don't mind about C99, i'd like gcc not to be aware of
    its existence. when C89/C90 was made (1989/1990) C99 didn't existed, so
    why telling me my program can produce different results if compiled with
    C99 standard? C99 doesn't exist...

    i hope it's clear what i mean...
     
    fctk, Apr 1, 2006
    #6
  7. fctk

    Michael Mair Guest

    fctk schrieb:
    > Eric Sosman wrote:
    >
    >> The compiler is warning you that the rules changed
    >> between C90 and C99, and that the type of the constant
    >> depends on which Standard you follow -- to put it another
    >> way, the type of the constant is "unstable" in the sense
    >> that it could change with a compiler upgrade.

    >
    >
    > Jack Klein wrote:
    >
    >> That's because the rules changed in 1999.

    >
    >
    > Clark S. Cox III wrote:
    >
    >> Because under C99, the type of the constant is "long long" (which is
    >> signed),
    >> while under C90 (assuming 4 byte ints and longs), it is "unsigned
    >> long" (which
    >> is unsigned). Hence, the warning is telling you that your constant is
    >> unsigned
    >> under C90, but not under C99, and that you may get different results
    >> when you
    >> change compilers.

    >
    > ok, it seems you all agree on the reason of that warning.
    >
    > i tried to specify -std=iso9899:1990 (C89/C90) in the gcc parameters
    > list, but i get that warning again.
    >
    > i still wonder. i don't mind about C99, i'd like gcc not to be aware of
    > its existence. when C89/C90 was made (1989/1990) C99 didn't existed, so
    > why telling me my program can produce different results if compiled with
    > C99 standard? C99 doesn't exist...
    >
    > i hope it's clear what i mean...


    Yes.
    This is rather a request to the compiler to not warn you about
    problems other people might have on other compilers when
    compiling your code.

    Note that, in principle, a compiler can warn you about everything
    it likes to ("Your code contains 42 'i's -- that is a bad omen on
    days like this one").
    Maybe, in gnu.gcc.help someone can tell you how to achieve that
    (or maybe you find something in the gcc documentation yourself).

    However, if you go this way, then consider at least protecting
    these others (or maybe even yourself) from errors:
    #if __STDC_VERSION__ >= 199901L
    # error My code does not work for C99 or newer standards
    #endif

    If you are maintaining old code and if this warning comes up at
    hundreds of different places, switching off or filtering this
    warning and putting the above in one source file may be a
    sensible way to go. The decision should be clearly documented
    somewhere.
    If you are writing new code, then the warning is justified and
    removing its cause as often as it comes up is just sensible --
    why leave unnecessary and potentially dangerous degrees of
    freedom in your code if you can say exactly what you mean?


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Apr 1, 2006
    #7
    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. Nan Li
    Replies:
    1
    Views:
    1,470
    Juha Nieminen
    Dec 14, 2008
  2. Shaguf
    Replies:
    0
    Views:
    541
    Shaguf
    Dec 24, 2008
  3. Shaguf
    Replies:
    0
    Views:
    496
    Shaguf
    Dec 26, 2008
  4. Shaguf
    Replies:
    0
    Views:
    269
    Shaguf
    Dec 26, 2008
  5. Shaguf
    Replies:
    0
    Views:
    245
    Shaguf
    Dec 24, 2008
Loading...

Share This Page