当printf的相应参数不是short/char时,使用h或hh长度修饰符是否非法?
当printf的相应参数不是short/char时,使用h或hh长度修饰符是否非法?,c,printf,language-lawyer,undefined-behavior,short,C,Printf,Language Lawyer,Undefined Behavior,Short,printf函数族提供了一系列长度修饰符,其中两个是hh(表示有符号字符或无符号字符参数提升为int)和h(表示提升为int的signed short或unsigned short参数)。历史上,这些长度修饰符的引入只是为了与scanf的长度修饰符对称,很少用于printf 以下是ISO 9899:2011§7.21.6.1“fprintf功能”7的摘录: 7长度修饰符及其含义为: hh指定以下转换说明符应用于有符号字符或无符号字符参数(参数将根据整数升迁进行升迁,但其值应在打印前转换为有符号
printf
函数族提供了一系列长度修饰符,其中两个是hh
(表示有符号字符
或无符号字符
参数提升为int
)和h
(表示提升为int
的signed short
或unsigned short
参数)。历史上,这些长度修饰符的引入只是为了与scanf
的长度修饰符对称,很少用于printf
以下是ISO 9899:2011§7.21.6.1“fprintf功能”7的摘录:
7长度修饰符及其含义为:
指定以下转换说明符应用于hh
或有符号字符
参数(参数将根据整数升迁进行升迁,但其值应在打印前转换为无符号字符
或有符号字符
);或者以下无符号字符
转换说明符应用于指向有符号字符的指针 争论n
指定下列h
,d
,i
,o
,u
或x
转换说明符应用于x
或短int
参数(参数将根据整数提升进行提升,但其值应在打印前转换为无符号短int
或short int
);或者以下无符号short int
转换说明符应用于指向shortn
参数的指针int
n
转换说明符的情况,这些几乎相同的段落如何描述h
和hh
的行为
- 在中,有人声称,对于带有
或h
长度修饰符的转换规范,传递超出hh
、有符号字符
、或无符号字符
范围的参数是未定义的行为,因为参数未转换分别从类型无符号短字符
,char
等开始short
- 我声明该函数以定义良好的方式对
类型的每个值进行操作,int
的行为就好像参数在转换之前分别被转换为printf
,char
等short
- 还可以说,在默认参数提升之前,使用不属于相应类型的参数调用函数是未定义的行为,但这似乎很难理解
§7.21.6.1¨7(如果有的话)的这三种解释中,哪一种是正确的?本标准规定: 如果任何参数不是相应转换规范的正确类型,则行为未定义 [C2011 7.21.6.1/9] “正确类型”的含义可以理解,但对我来说最合理的解释是转换规范“适用于”的类型如同一节前面所述,以及问题中部分引用的。我认为关于论点提升的附加评论是承认普通论点通过规则,并避免将这些功能作为特殊情况的任何含义。我不认为附加评论与确定参数的“正确类型” 如果你传递了一个比转换规范正确的更宽类型的参数,那么实际会发生什么呢?这是一个不同的问题。我倾向于相信C系统不太可能被任何人实现,以至于它会影响a
printf()
参数实际上是一个char
,或者它是否是一个int
,其值是否在char
范围内。但是,我断言,编译器检查参数类型与格式的对应关系并在不匹配时拒绝程序是有效的行为(因为在这种情况下所需的行为没有明确定义)
另一方面,我可以肯定地想象
printf()
实现实际上是不正常的(打印垃圾、损坏内存、吃午餐)如果参数的值超出了相应转换说明符所暗示的范围。由于行为未定义,这也是允许的。我提出了第一个主张(请参见链接答案)。我确实认为,如果我们对段落中使用的词语过于迂腐,我的主张就站得住脚(升级前的论据是一个简短的
变体),但这一段/C的精神使得fuzzxl
的说法更有可能。我认为第一种方法是正确的。转换例程很可能期望有限的范围,因此使用优化的版本(只需考虑8位或16位CPU)。不确定输入参数是否必须是同一类型。问题是,格式字符串解析器如何判断“true”"int
从short
/等转换为int
的输入参数。另一个方面可能是编译器的内联。在最坏的情况下,它可能会抑制优化,但没有其他功能,因为它必须具有相同的行为。此行有点不清楚-%h……但它的值应在转换之前转换为short int或unsigned short int int(ore打印)
。那么这是否意味着它可以保存大于无符号short int/short int
的值,因为它经历了整数升级?如果是,那么它保存的值将转换回其原始变量类型?结果会是什么?如果是