Old Wolf said:
You caused undefined behaviour by not passing an argument of
type 'short int' to %hd
Interesting.
In the description of fprintf(), C99 7.19.6.1p7 says that the 'h'
modifier
Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a short int or unsigned short int argument
(the argument will have been promoted according to the integer
promotions, but its value shall be converted to short int or
unsigned short int before printing);
[...]
and p9 says:
[...] If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.
But is the "correct type" for "%hd" short, or is it int?
If the correct type is short, then the following two calls:
printf("%hd\n", (short)42);
printf("%hd\n", 42);
can behave differently, and the latter invokes undefined behavior.
For any user-written variadic function that uses <stdarg.h>, the two
calls are identical; the "(short)42)" argument is promoted to int
before the call.
The standard doesn't say that printf() uses <stdarg.h>. Conceivably
the compiler could treat printf() specially, but it would be difficult
(but not impossible) to do this for calls through a pointer, where the
compiler doesn't know whether it's calling printf() or an equivalent
user-defined variadic function.
Things would be more consistent if the "correct type" for "%hd" were
int rather than short.