I recently read that
unsigned char x=1;
printf(\"%u\",x);
invokes undefined behaviour since due to the format specifier %u, printf expects
Since printf
uses a variable argument list, it will be unpacked via va_arg
. C++ refers to the C standard for va_arg
rules. The C99 Standard says the following:
The
va_arg
macro expands to an expression that has the specified type and the value of the next argument in the call. The parameterap
shall have been initialized by theva_start
orva_copy
macro (without an intervening invocation of theva_end
macro for the sameap
). Each invocation of theva_arg
macro modifiesap
so that the values of successive arguments are returned in turn. The parameter type shall be a type name specified such that the type of a pointer to an object that has the specified type can be obtained simply by postfixing a*
to type. If there is no actual next argument, or if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases:
- one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types;
- one type is pointer to void and the other is a pointer to a character type.
Clearly, integer promotions are taken into account when determining whether the actual and expected type match. And signed vs unsigned mismatch is covered by the first bullet point.
Since x = 1
is certainly a value representable by unsigned int
, and promotion of unsigned char
generates either signed int
(if INT_MAX >= UCHAR_MAX
) or unsigned int
(if INT_MAX < UCHAR_MAX
), this is perfectly legal.