Помимо %hn
и %hhn
(где h
или hh
определяют размер объекта указанный), в чем смысл модификаторов h
и hh
для спецификаторов формата printf
?
Из-за продвижения по умолчанию, которое требуется стандартом для применения к функциям с переменным числом аргументов, невозможно передать аргументы типа char
или short
(или любые их варианты со знаком/без знака) в printf
.
Согласно 7.19.6.1(7), модификатор h
:
Указывает, что следующий спецификатор преобразования d, i, o, u, x или X применяется к аргументу типа short int или unsigned short int (аргумент будет повышен в соответствии с продвижением целых чисел, но его значение должно быть преобразовано в тип short int). или unsigned short int перед печатью); или что следующий спецификатор преобразования n применяется к указателю на короткий аргумент типа int.
Если аргумент на самом деле имел тип short
или unsigned short
, то повышение до int
с последующим преобразованием обратно в short
или unsigned short
даст то же значение, что и повышение до int
без какого-либо обратного преобразования. Таким образом, для аргументов типа short
или unsigned short
, %d
, %u
и т. д. должны давать результаты, идентичные %hd
, %hu
и т. д. (и аналогично для типов char
и hh
).
Насколько я могу судить, единственная ситуация, когда модификатор h
или hh
может быть полезен, — это когда аргумент передает ему int
вне диапазона short
или unsigned short
, например
printf("%hu", 0x10000);
но я понимаю, что передача неправильного типа в любом случае приводит к неопределенному поведению, так что вы не можете ожидать, что он напечатает 0.
Один реальный случай, который я видел, это такой код:
char c = 0xf0;
printf("%hhx", c);
где автор ожидает, что он напечатает f0
, несмотря на то, что реализация имеет простой подписанный тип char
(в этом случае printf("%x", c)
напечатает fffffff0
или подобное). Но оправдано ли это ожидание?
(Примечание: происходит то, что исходный тип был char
, который повышается до int
и преобразуется обратно в unsigned char
вместо char
, таким образом изменяя печатаемое значение. Но определяет ли стандарт такое поведение или это деталь реализации на что может полагаться сломанное программное обеспечение?)