The printf
family of functions provide a series of length modifiers, two of them being hh
(denoting a signed char
or unsigned char
argument promoted to int
) and h
(denoting a signed short
or unsigned short
argument promoted to int
). Historically, these length modifiers have only been introduced to create symmetry with the length modifiers of scanf
and are rarely used for printf
.
Here is an excerpt of ISO 9899:2011 §7.21.6.1 “The fprintf function” ¶7:
7 The length modifiers and their meanings are:
hh
Specifies that a followingd
,i
,o
,u
,x
, orX
conversion specifier applies to asigned char
orunsigned char
argument (the argument will have been promoted according to the integer promotions, but its value shall be converted tosigned char
orunsigned char
before printing); or that a followingn
conversion specifier applies to a pointer to a signed char argument.
h
Specifies that a followingd
,i
,o
,u
,x
, orX
conversion specifier applies to ashort int
orunsigned short int
argument (the argument will have been promoted according to the integer promotions, but its value shall be converted toshort int
orunsigned short int
before printing); or that a followingn
conversion specifier applies to a pointer to a shortint
argument....
Ignoring the case of the n
conversion specifier, what do these almost identical paragraphs say about the behaviour of h
and hh
?
- In this answer, it is claimed that passing an argument that is outside the range of a
signed char
,signed short
,unsigned char
, orunsigned short
resp. for a conversion specification with anh
orhh
length modifier resp. is undefined behaviour, as the argument wasn't converted from typechar
,short
, etc. resp. before. - I claim that the function operates in a well-defined manner for every value of type
int
and thatprintf
behaves as if the parameter was converted tochar
,short
, etc. resp. before conversion. - One could also claim that invoking the function with an argument that was not of the corresponding type before default argument promotion is undefined behaviour, but this seems abstruse.
Which of these three interpretations of §7.21.6.1¶7 (if at all) is correct?
short
variant) but the spirit of this paragraph/C makesFUZxxl
's claim maybe more likely. – ouahint
input argument from ashort
/etc. converted toint
. Another aspect might be inlining by the compiler. At worst it might inhibit optimization, but nothing else, as it has to behave the same. – too honest for this site%h......but its value shall be converted to short int or unsigned short int before printing)
. So does it mean that it can hold values greater thanunsigned short int /short int
as it is undergone integer promotion ? And if so than value it hold is converted back to its original variable type ? What will be its outcome ? – ameyCU%hhd
, then you are going to hurt, because this will take up 8 bytes, andprintf
will expect it to take 4 (windows and Linux x86 anyway) – Bensigned
orunsigned int
arguments, as these are the types expected forh
andhh
due to default argument promotions. – fuz