The printf
函数族提供了一系列长度修饰符,其中两个是hh
(表示一个signed char
or unsigned char
论点提升为int
) and h
(表示一个signed short
or unsigned short
论点提升为int
)。从历史上看,引入这些长度修饰符只是为了与以下长度修饰符创建对称性:scanf
并且很少用于printf
.
以下是 ISO 9899:2011 §7.21.6.1“fprintf 函数”¶7 的摘录:
7 长度修饰符及其含义是:
hh
指定以下d
, i
, o
, u
, x
, or X
转换说明符适用于signed char
or unsigned char
参数(参数将根据整数提升进行提升,但其值应转换为signed char
or unsigned char
打印前);或者以下n
转换说明符适用于指向有符号字符的指针
争论。
h
指定以下d
, i
, o
, u
, x
, or X
转换说明符适用于short int
or unsigned short int
参数(参数将根据整数提升进行提升,但其值应转换为short int
or unsigned short int
打印前);或者以下n
转换说明符适用于指向短整型的指针int
争论。
...
忽略案例n
转换说明符,这些几乎相同的段落对以下行为有何说明h
and hh
?
- In 这个答案,据称传递一个超出 a 范围的参数
signed char
, signed short
, unsigned char
, or unsigned short
分别。对于转换规范h
or hh
长度修饰符分别是未定义的行为,因为参数没有从类型转换而来char
, short
等。前。
- 我声称该函数对于每个类型值都以明确定义的方式运行
int
然后printf
其行为就像参数被转换为char
, short
等。转换前。
- 人们还可以声称,在默认参数提升之前使用不属于相应类型的参数调用函数是未定义的行为,但这似乎很深奥。
§7.21.6.1¶7 的这三种解释(如果有的话)哪一种是正确的?
该标准规定:
如果任何参数不是相应转换规范的正确类型,则行为未定义。
[C2011 7.21.6.1/9]
“正确的类型”的含义可以想象,可以解释,但对我来说最合理的解释是转换规范“适用于”的类型,如同一节前面所指定的,以及部分引用的,的问题。我采取括号内的关于参数提升的评论要承认普通的参数传递规则,并避免这些函数是特殊情况的任何暗示。我不认为括号中的注释与确定参数的“正确类型”相关。
如果您传递的参数类型比转换规范的正确类型更宽,实际会发生什么是另一个问题。我倾向于相信 C 系统不太可能被任何人实现,因此它是否会产生影响printf()
论证实际上是一个char
,或者是否是一个int
其值在范围内char
。然而,我断言,编译器检查参数类型与格式的对应关系,并在不匹配的情况下拒绝程序是有效的行为(因为在这种情况下所需的行为是明确未定义的)。
另一方面,我当然可以想象printf()
如果参数的值超出相应转换说明符隐含的范围,则实现实际上会出现错误(打印垃圾、损坏内存、吃掉你的午餐)。由于行为未定义,这也是允许的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)