The following program has undefined behavior:
#include <stdio.h>
int main(void)
{
unsigned int x = -100; // This is fine, becomes UINT_MAX - 100
printf("%d\n", x); // This is undefined behavior.
return 0;
}
C99 7.19.6.1p8 states %d expects an int argument.
C99 7.19.6.1p9 states "If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."
However, gcc -Wformat
(which is included with -Wall
) will not complain about the above program, why? Is this a bug, or a deliberate omission?
From the gcc manpage:
-Wformat
Check calls to "printf"
and "scanf"
, etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense
Well the basic answer is – nothing. No bits are changed, the compiler just treats the bit representation as unsigned. For example, let us assume that the compiler represents signed integers using 2's complement notation (this is the norm – but is *not* mandated by the C language).
The Google C++ style guide recommends avoiding unsigned integers except in situations that definitely require it (for example: file formats often store sizes in uint32_t or uint64_t -- no point in wasting a signedness bit that will never be used).
An int is signed by default, meaning it can represent both positive and negative values. An unsigned is an integer that can never be negative. If you take an unsigned 0 and subtract 1 from it, the result wraps around, leaving a very large number (2^32-1 with the typical 32-bit integer size).
The 32-bit unsigned int data type can hold integer values in the range of 0 to 4,294,967,295. You may also refer to this data type simply as unsigned.
My best guess is that the warning is skipped because the UB is arguably invoked by the value and not merely by the type. va_arg
allows the signedness to mismatch as long as the value is representable in both the signed and unsigned type. However, printf
and friends are not specified in terms of va_arg
and the standard states that any type mismatch results in UB, but this is probably a bug in the standard. Otherwise, printf("%x",1);
would invoke UB. See my question on the topic:
Does printf("%x",1) invoke undefined behavior?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With