Search code examples
cgcccompiler-warningsgcc-warningunsigned-integer

C iteration up to a very large number - compiler warning about unsigned int


I have the following piece of code :

#include <stdio.h>
#define POWER 10000000000000000000

int main()
{
    int i;
    for (i = 0; i < POWER; i++)
    {
         ....
    }
    return 0;
}

and the compiler gives me the following warnings :

ex1.c:33:19: warning: integer constant is so large that it is unsigned [enabled by default] ex1.c:33:2: warning: this decimal constant is unsigned only in ISO C90 [enabled by default]

How can I iterate with i running through all the values until it reaches POWER? I tried declaring i as unsigned int but the warnings remain.


Solution

  • Your constant 10000000000000000000 requires 64 bits to represent it. In hexadecimal, it's 0x8ac7230489e80000. It can be represented in an unsigned 64-bit type, but not in a signed 64-bit type.

    As of C99, all integer constants are of some signed type: the first of int, long int, or long long int in which the value will fit.

    C90 (which didn't yet have long long int) had different rules. In C90, an unsuffixed decimal integer constant is of type int, long int, or unsigned long int.

    gcc's default mode is -std=gnu90, which supports the C90 standard plus GNU-specific extensions. If you're on a 64-bit system, long and unsigned long is 64 bits. Under C90 rules, your constant is of type unsigned long (assuming unsigned long is at least 64 bits). Under C99 and later rules, assuming there's no integer type wider than 64 bits, it's a constraint violation. (gcc version 5 changed the default to -std=gnu11.)

    The compiler, which apparently is operating under C90 rules, is warning you that the meaning of 10000000000000000000 differs depending on which edition of the standard the compiler is operating under.

    You can make your program "work" with the following changes:

    #define POWER 10000000000000000000ULL // suffix to specify the type
    ...
    for (unsigned long long = 0; i < POWER; i ++)
    ...
    

    But although that makes the program valid, it doesn't make it practical. At one iteration per nanosecond, it will take more than 3 centuries for that loop to finish. My own reasonably modern computer executes one iteration of an empty for loop in about 1.6 nanoseconds. Whatever problem you're trying to solve, I suggest either finding a different way to solve it, or reducing it to a smaller problem. The fastest way to execute that loop is to wait a few decades for hardware to become faster and then compile and execute it.

    (This assumes the body of the loop is non-trivial. If the body of the loop does nothing, the compiler might optimize away the loop altogether.)