当 printf 的相应参数不是 short / char 时,使用 h 或 hh 长度修饰符是否非法?

Is it illegal to use the h or hh length modifiers when the corresponding argument to printf was not a short / char?

printf 系列函数提供了一系列长度修饰符,其中两个是 hh(表示 signed charunsigned char 参数提升为 int) 和 h(表示 signed shortunsigned short 参数提升为 int)。从历史上看,这些长度修饰符只是为了与 scanf 的长度修饰符创建对称而引入,很少用于 printf.

这是 ISO 9899:2011 §7.21.6.1“fprintf 函数”¶7 的摘录:

7 The length modifiers and their meanings are:

  • hh Specifies that a following d, i, o, u, x, or X conversion specifier applies to a signed char or unsigned char argument (the argument will have been promoted according to the integer promotions, but its value shall be converted to signed char or unsigned char before printing); or that a following n conversion specifier applies to a pointer to a signed char argument.

  • h Specifies that a following d, i, o, u, x, or X conversion specifier applies to a short int or unsigned short intargument (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); or that a following n conversion specifier applies to a pointer to a short int argument.

  • ...

忽略 n 转换说明符的大小写,这些几乎相同的段落对 hhh 的行为说了什么?

§7.21.6.1¶7(如果有的话)的这三种解释中哪一种是正确的?

标准规定:

If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

[C2011 7.21.6.1/9]

"the correct type" 的含义可以想象得到解释,但对我来说最合理的解释是同一部分前面指定的转换规范 "applies to" 的类型,并且作为在问题中部分引用。我认为关于参数提升的 括号 评论承认普通的参数传递规则,并避免这些函数是特殊情况的任何暗示。我不认为括号中的评论与确定参数的 "correct type" 有关。

如果您传递的参数类型比转换规范的正确类型更宽,实际会发生什么是另一个问题。我倾向于相信 C 系统不太可能被任何人实现,以至于 printf() 参数实际上是一个 char,还是一个 int值在 char 范围内。但是,我断言,编译器检查参数类型与格式的对应关系并在不匹配时拒绝程序是有效的行为(因为在这种情况下所需的行为是明确未定义的)。

另一方面,如果参数的值超出相应转换说明符隐含的范围,我当然可以想象 printf() 实现实际上行为不当(打印垃圾、损坏内存、吃你的午餐) .由于行为未定义,这也是允许的。