Search code examples
clong-integerimplicit-conversionunsignedunsigned-integer

C compiler not recognizing unsigned long


On my computer, long takes a maximum value of 9223372036854775807. However, when I tired unsigned long with a larger value the compiler throws a warning saying it needs to be interpreted as an unsigned long when I already had it defined as so. Why is that the case?

//assigning maximum value of a long integer. (No error)
long max_l = 9223372036854775807L;

//assigning an unsigned long integer.
unsigned long max_ul = 9223372036854775808L; //warning: integer literal is too large to be represented in a signed
                                             //integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal]

cc --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)

Solution

  • This integer constant:

    9223372036854775808L
    

    is too large to be stored in a long.

    Instead, use:

    9223372036854775808UL
    

    This specifies that the constant has the type unsigned long by appending the suffix UL

    Or just use the suffix U:

    unsigned long max_ul = 9223372036854775808U;
    

    When an integer constant has the suffix L (or l) then the compiler determines its type in the following order: the first of the types

    signed long
    signed long long
    

    in which its value can be represented. It seems that the type signed long has the same integer representation as the type signed long long established by the compiler. So neither the type signed long nor the type signed long long can represent the constant. The constant is too big for these types. But the type unsigned long that has the same internal representation as the type unsigned long long established by the compiler can represent the constant.

    Pay also attention to that there are no negative integer constants in C. If for example you will write

    int x = -1;
    

    then the compiler splits the construction -1 into two tokens: the integer constant 1 and the unary operator -.

    Consider the following demonstrative program

    #include <stdio.h>
    
    int main(void) 
    {
        int a[] = { 0, 1, 2 };
        int *p = a + 1;
    
        printf( "p[-1] = %d\n", p[-1] );
        printf( "-1[p] = %d\n", -1[p] );
    
        return 0;
    }
    

    The program output is

    p[-1] = 0
    -1[p] = -2
    

    The expression -1[p] is not the same as the expression (-1)[p]. It is processed as -(1[p] ) that is equivalent to -p[1].