What is the purpose of the h and hh modifiers for printf?

Aside from %hn and %hhn (where the h or hh specifies the size of the pointed-to object), what is the point of the h and hh modifiers for printf format specifiers?

Due to default promotions which are required by the standard to be applied for variadic functions, it is impossible to pass arguments of type char or short (or any signed/unsigned variants thereof) to printf.

According to 7.19.6.1(7), the h modifier:

Specifies that a following d, i, o, u, x, or X conversion specifier applies to a аргумент short int или unsigned short int (аргумент будет были продвинуты согласно целочисленным акциям, но его значение должно перед печатью преобразовать в short int или unsigned short int); или что следующий спецификатор преобразования n применяется к указателю на короткий int argument.

If the argument was actually of type short or unsigned short, then promotion to int followed by a conversion back to short or unsigned short will yield the same value as promotion to int without any conversion back. Thus, for arguments of type short or unsigned short, %d, %u, etc. should give identical results to %hd, %hu, etc. (and likewise for char types and hh).

As far as I can tell, the only situation where the h or hh modifier could possibly be useful is when the argument passed it an int outside the range of short or unsigned short, e.g.

printf("%hu", 0x10000);

but my understanding is that passing the wrong type like this results in undefined behavior anyway, so that you could not expect it to print 0.

One real world case I've seen is code like this:

char c = 0xf0;
printf("%hhx", c);

where the author expects it to print f0 despite the implementation having a plain char type that's signed (in which case, printf("%x", c) would print fffffff0 or similar). But is this expectation warranted?

(Note: What's going on is that the original type was char, which gets promoted to int and converted back to unsigned char instead of char, thus changing the value that gets printed. But does the standard specify this behavior, or is it an implementation detail that broken software might be relying on?)

55
задан hippietrail 27 April 2011 в 16:55
поделиться