Search code examples
clong-integerunsigned

What is the exact value range for unsigned long?


I am working through the exercises in the book "Learn C the hard way". Exercise 7 asks the reader to find the value which makes the range of an unsigned long exceed.

Change long to unsigned long and try to find the number that makes it too big.

So my approach is to first get the size of an unsigned long on my machine:

printf("SIZEOF ULONG: %lu", sizeof(unsigned long));

This prints 8 as a result. So assuming that an unsigned long will take up 64 bits on my machine I looked up the maximum range on Wikipedia.

64-Bits (word, doubleword, longword, long long, quad, quadword, qword, int64)

  • Unsigned: From 0 to 18,446,744,073,709,551,615

I was expecting that declaring an unsigned long with the above value would compile without warnings until I increment the value by 1. The result is different though. compiling the following program results in a warning.

#include <stdio.h>
int main()
{
    unsigned long value = 18446744073709551615;
    printf("SIZEOF ULONG: %lu", sizeof(unsigned long));
    printf("VALUE: %lu", value);
    return 0;
}

bla.c: In function ‘main’:
bla.c:5:27: warning: integer constant is so large that it is unsigned
     unsigned long value = 18446744073709551615;
                           ^~~~~~~~~~~~~~~~~~~~

So why does gcc complain about the value being to large, I thought I already declared it as unsigned?


Solution

  • Decimal integer constants have type int if they fit in that range, otherwise they have type long or long long. They do not have an unsigned type, and if the value is outside those signed ranges you get the warning. You need to add the ul suffix for the constant to have the proper type.

    There’s also a much easier way to get the maximum value of this type without knowing its size. Just cast -1 to this type.

    unsigned long value = (unsigned long)-1;