This is wrong:
printf("unsigned long long int:
%llu to %llu
", 0, ULONG_MAX);
You use a unsigned long long
format specifier, but you pass an int
and an unsigned long
value. Promotion rules mean you can be sloppy for everything int
-sized or smaller, which does not apply to long long
.
Use casts:
printf("unsigned long long int:
%llu to %llu
",
0ULL, (unsigned long long) ULONG_MAX);
Explanation: When passing arguments to printf
, any type that can fit in an int
is promoted to int
, and then any type that can fit in an unsigned int
is promoted to unsigned int
. It is also okay to pass an unsigned type to a signed format specifier or vice versa as long as the value passed can be represented using the type specified by the format specifier.
So you must be careful with long
and long long
, but you can be sloppy with int
, short
, and char
.
Most compilers have settings to make them warn you about this type of error, since it can be detected at compile-time fairly easily; GCC and Clang have -Wformat
which results in the following warnings:
test.c:5: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 2 has type ‘int’
test.c:5: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 3 has type ‘long unsigned int’
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…