Assigning constant values to long variables
Although type identification of constants follows explicit rules in C and C++, many programs use hexadecimal or unsuffixed constants as "typeless" variables and rely on a twos complement representation to truncate values that exceed the limits permitted on a 32-bit system.
long type in
64-bit mode, unexpected results can occur, generally at the following boundary areas: - constant >
UINT_MAX - constant <
INT_MIN - constant >
INT_MAX
| Constant assigned to long | Equivalent value | 32-bit mode | 64-bit mode |
|---|---|---|---|
| –2,147,483,649 | INT_MIN–1 | +2,147,483,647 | –2,147,483,649 |
| +2,147,483,648 | INT_MAX+1 | –2,147,483,648 | +2,147,483,648 |
| +4,294,967,726 | UINT_MAX+1 | 0 | +4,294,967,296 |
| 0xFFFFFFFF | UINT_MAX | –1 | +4,294,967,295 |
| 0x100000000 | UINT_MAX+1 | 0 | +4,294,967,296 |
| 0xFFFFFFFFFFFFFFFF | ULONG_MAX | –1 | –1 |
Unsuffixed constants can lead
to type ambiguities that can affect
other parts of your program, such as when the results of sizeof operations
are assigned to variables. For example, in 32-bit mode, the
compiler types
a number like 4294967295 (UINT_MAX) as an unsigned
long and sizeof returns 4 bytes. In 64-bit mode,
this same number becomes a signed long and sizeof returns
8 bytes. Similar problems occur when the compiler passes constants
directly to functions.
You can avoid these problems
by using the suffixes L (for
long constants), UL (for unsigned long constants), LL
(for long long constants), or ULL (for unsigned long
long constants) to explicitly type all constants that have the potential
of affecting assignment or expression evaluation in other parts of
your program. In the example cited in the preceding paragraph, suffixing
the number as 4294967295U forces the compiler to
always recognize the constant as an unsigned int in 32-bit or
64-bit mode. These suffixes can also be applied to
hexadecimal constants.