printf(“%d\n”, 4294967296); makes some strange errors
Yes it does - a most interesting question.
This comes down to what is the type of 4294967295 and 4294967296?
Is the type determined by fitting in:
int, long, unsigned long
(C89)
int, long, long long
(C99)
int, long, unsigned long, long long, unsigned long long
(Perhaps VS2017)
Note: 4294967295 + 1
is not signed integer overflow in any case.
This is one of the places where C89, C99 (or later) differ and where VS2017 does its own thing.
With compliant C89, (32-bit world) 4294967295 is a unsigned long
decimal constant and adding 1 is unsigned long
0. (C89 6.1.3.2)
As ...
arguments, an int 0
and unsigned 0
both work for "%u"
and "%d"
and the value of 0 is in range for both. Yet this is an unsigned long 0
and so technical undefined behavior (UB). On 32-bit systems, this UB is often benign and results in the same as printing a unsigned 0
.
4294967296 is simply an out of range constant.
With C99 (or later - certainly not OP's case), 4294967295 is a long long
decimal constant1 and adding 1 is simply long long
4294967296. 4294967296 is another long long
decimal constant
Passing a long long
to match a "%d"
or "%u"
is undefined behavior. The same output of "0, 1, 0" in both cases would be an "expected" UB.
Yet OP is using VS2017 and 4294967295 is a unsigned long
decimal constant (per C89 rules) and int, long int, or unsigned long int and adding 1 is unsigned long
0. Printing that with %u,%d
is technically UB, but with 32-bit unsigned
having the same characteristic as 32-bit unsigned long
the 0,0,0 output is reasonable.
4294967296 is apparently some 64-bit type (such as long long
)2 and per C99 rules is UB. Output of 0, 1, 0 is reasonable, yet not resilient.
OP's result may differ depending on /Za, /Ze (Disable Language Extensions).
1 or a 64-bit long
.
2 I was unable to find a definitive on-line VS2017 ref for the type of a C decimal constant, (not C++) for values more than 4294967295.