如何解决在printf需要一个int的情况下,是否要给printf一个char参数的UB?
我是否正确理解该程序导致UB的标准:
#include <stdio.h>
int main(void)
{
char a = 'A';
printf("%c\n",a);
return 0;
}
当它在sizeof(int)==1 && CHAR_MIN==0
的系统上执行时?
由于a
是无符号的,并且大小与({1)}相同(1),因此它将提升为int
[1](2),而不是unsigned int
,因为int
不能代表int
的所有值。格式说明符char
期望"%c"
[2],并且在int
中使用错误的符号会导致UB [3]。
C99的ISO / IEC 9899相关报价
[1]根据C99 6.3.1.1:2晋升为printf()
:
如果
int
可以代表原始类型的所有值,则该值为 转换为int
;否则,它将转换为int
。 这些称为整数促销。所有其他类型是 不受整数促销的影响。
[2]格式说明符unsigned int
需要一个"%c"
参数C99 7.19.6.1:8 int
:
如果不存在
c
长度修饰符,则l
参数将转换为int
,然后写入结果字符。
[3]在unsigned char
(3)中使用错误的类型(包括错误的签名)会导致根据C99 7.19.6.1:9的UB:
...如果任何参数不是对应参数的正确类型 转换规范,其行为是不确定的。
fprintf()
宏给出了具有不同符号的相同类型的异常,但va_arg
没有给出,并且不要求printf()
使用printf()
(4)。
脚注: (标记为( n ))
-
这意味着
va_arg
,因为INT_MAX==SCHAR_MAX
没有填充。 -
相同的规则适用于
char
,请参见C99 7.19.6.3:2
解决方法
一个程序可以具有未定义的行为,取决于实现的特征。
例如,一个执行的程序
int x = 32767;
x++;
(在其他方面定义良好)在INT_MAX> 32767的实现中具有良好定义的行为,否则具有未定义的行为。
您的程序:
#include <stdio.h>
int main(void)
{
char a='A';
printf("%c\n",a);
return 0;
}
对于任何使用INT_MAX >= CHAR_MAX
的托管实现,都有明确定义的行为。在任何此类实现中,'A'
的值都会提升为int
所期望的%c
。
如果INT_MAX < CHAR_MAX
(这意味着纯char
是无符号的且CHAR_BIT >= 16
),则a
的值将提升为unsigned int
。 N1570 7.21.6.1p9:
如果任何参数不是对应参数的正确类型 转换规范,其行为是不确定的。
暗示这具有未定义的行为。
实际上,(a)这种实现很少见,很可能不存在(我听说过CHAR_BIT > 8
的仅有的C实现是DSPs的,并且这些实现很可能是独立的), (b)任何此类实现都可能旨在优雅地处理此类情况。
TL; DR没有UB(以我的解释,无论如何)。
6.2.5类型
6.对于每个有符号整数类型,都有一个对应的(但不同的)无符号整数类型(用关键字unsigned表示)使用相同的存储量(包括符号信息)并且具有相同的对齐要求。 > 9.有符号整数类型的非负值范围是相应的无符号整数类型的子范围,并且每种类型中相同值的表示形式都相同 41)
41)相同的表示形式和对齐要求旨在表示与函数的参数,函数的返回值和并集成员相同的可互换性。
此外
7.16.1.1 va_arg宏
2 va_arg宏扩展为具有指定类型和调用中下一个参数值的表达式。 [...]如果没有实际的下一个自变量,或者类型与实际的下一个自变量的类型不兼容(根据默认自变量的提升),则该行为是不确定的,除了以下情况: / p>
- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且值在两种类型中均可表示;
7.21.6.8 vfprintf函数
288) [...]函数vfprintf,vfscanf,vprintf,vscanf,vsnprintf,vsprintf和vsscanf调用va_arg宏[...]
因此,只要值在范围内,就可以认为无符号类型不是不是“对应(带符号)转换规范的错误类型”。
以下事实得到了证实,即即使主要的编译器也确实警告其他不匹配,即使它们在给定平台上具有相同的表示形式(例如{{1 }}和long
。
我是否了解该程序导致UB的标准正确信息?
#include <stdio.h> int main(void) { char a='A'; printf("%c\n",a); return 0; }
何时在sizeof(int)== 1 && CHAR_MIN == 0的系统上执行?
这可能是对该标准的合理解释。但是,如果产生了具有这种类型特征组合的实现以供真正使用,则我完全有信心,它将为%c
指令提供适当的支持-作为扩展,如果要解释的话这样。这样,无论C标准是否也被解释为定义该行为,示例程序都将对该实现具有明确定义的行为。我想我认为实现质量问题是“为了真正使用”而汇总的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。