c – 为什么参数与printf未定义的行为中的转换说明符不匹配?

c – 为什么参数与printf未定义的行为中的转换说明符不匹配?,第1张

概述在C(n1570 7.21.6.1/10)和C(通过包含C标准库)中,未定义的行为是为printf提供其类型与其转换规范不匹配的参数.一个简单的例子: printf("%d", 1.9) 格式字符串指定int,而参数是浮点类型. 这个问题的灵感来自于一个用户遇到遗留代码的问题,这些代码存在大量的转换不匹配,这显然没有任何损害,参见undefined behaviour in theory and 在C(n1570 7.21.6.1/10)和C(通过包含C标准库)中,未定义的行为是为printf提供其类型与其转换规范不匹配的参数.一个简单的例子:

printf("%d",1.9)

格式字符串指定int,而参数是浮点类型.

这个问题的灵感来自于一个用户遇到遗留代码的问题,这些代码存在大量的转换不匹配,这显然没有任何损害,参见undefined behaviour in theory and in practice.

声称格式不匹配UB起初看起来很激烈.很明显,输出可能是错误的,具体取决于精确的不匹配,参数类型,字节序,可能的堆栈布局和其他问题.正如一位评论员指出的那样,这也延伸到后来的(甚至是之前的?)论点.但这远不是一般的UB.就个人而言,除了预期的错误输出外,我从未遇到任何其他问题

冒险猜测,我会排除对齐问题.我能想象的是提供一个格式字符串,使得printf期望大数据和小的实际参数可能让printf读取超出栈,但我缺乏对var args机制和特定printf实现细节的深入了解来验证.

我快速浏览了一下printf sources,但它们对于休闲读者来说非常不透明.

因此我的问题是:在printf中错误匹配转换说明符和参数的具体危险是什么使它成为UB?

解决方法 一些编译器可以以允许的方式实现变量格式参数
要验证的参数类型;因为程序陷阱不正确
使用可能比输出看起来有效但错误的更好
信息,一些平台可能会选择这样做.

因为陷阱的行为超出了C标准的范围,所以任何动作
可能合理陷阱的类别被归类为调用未定义的行为.

请注意,基于错误格式化实现陷阱的可能性意味着即使在期望类型和实际传递类型具有相同表示的情况下,行为也被视为未定义,除非相同等级的有符号和无符号数字是可互换的(如果值为保持在两者共有的范围内[即如果“long”保持23,则可以输出“%lX”但不输出“%X”,即使“int”和“long”具有相同的大小].

另请注意,C89委员会引入了一个法令规则,该规则至今仍然存在,即使“int”和“long”具有相同的格式,代码:

long foo=23;int *u = &foo;(*u)++;

调用未定义的行为,因为它导致写入类型为“long”的信息被读作类型“int”(如果类型为“unsigned int”,行为也将是Undefined).由于“%X”格式说明符会导致数据被读取为“unsigned int”类型,因此将数据作为“long”类型传递几乎肯定会导致数据存储在“long”的某处,但随后将其读作“unsigned”类型int“,这种行为几乎可能违反上述规则.

总结

以上是内存溢出为你收集整理的c – 为什么参数与printf未定义的行为中的转换说明符不匹配?全部内容,希望文章能够帮你解决c – 为什么参数与printf未定义的行为中的转换说明符不匹配?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1223323.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存