When the suffix L or UL not used, the compiler uses the first type, which can contain a constant from a list (see details in the C99 standard, section 6.4.4: 5. For a decimal constant, list int , long int , long long int ).
As a result, in most cases there is no need to use a suffix. This does not change the meaning of the program. This does not change the initialization value of your example x for most architectures, although that would be if you chose a number that could not be represented as long long . See also codebauer's answer for an example where part of the U suffix is ββneeded.
There are several circumstances when a programmer may want to explicitly indicate the type of constant. One example is the use of a variational function:
printf("%lld", 1LL); // correct printf("%lld", 1); // undefined behavior
A common reason for using a suffix is ββthat the result of the calculation does not overflow. Two examples:
long x = 10000L * 4096L; unsigned long long y = 1ULL << 36;
In both examples, without suffixes, the constants would be of type int , and the calculation would be done as int . In each example, this carries the risk of overflow. The use of suffixes means that the calculation will be performed in a larger type instead, which has a sufficient range for the result.
According to Lightness Races in Orbit, the litteral suffix counts to . In the two examples above, simply declaring x as long and y as unsigned long long not enough to prevent overflow when evaluating the expressions assigned to it.
Another example is the comparison x < 12U , where the variable x is of type int . Without the U suffix, the compiler sets the constant 12 to int , and so the comparison is a comparison of signed ints.
int x = -3; printf("%d\n", x < 12);
With the suffix U comparison becomes a comparison of unsigned ints. "Normal arithmetic conversions" means that -3 is converted to a large unsigned int:
printf("%d\n", x < 12U); // prints 0 because (unsigned int)-3 is large
In fact, the type of constant can even change the result of an arithmetic calculation, again because of how the "regular arithmetic conversions" work.
Note that for decimal constants, the type list proposed by C99 does not contain an unsigned long long . In C90, the list ended with the largest standardized unsigned integer type at the time (which was unsigned long ). The consequence was that the value of some programs was changed by adding the standard long long type to C99: the same constant that was typed as an unsigned long in C90 can now be entered as a signed long long . I believe that for this reason, it was decided in C99 not to have an unsigned long long in the type list for decimal constants. See this and for an example. p>