【发布时间】:2021-01-02 14:33:02
【问题描述】:
我是否正确理解该程序导致 UB 的标准:
#include <stdio.h>
int main(void)
{
char a = 'A';
printf("%c\n", a);
return 0;
}
当它在sizeof(int)==1 && CHAR_MIN==0的系统上执行时?
因为如果a 是无符号的并且具有与int 相同的大小(1),它将被提升为unsigned int [1] (2),而不是int,因为a int 不能代表 char 的所有值。格式说明符 "%c" 需要 int [2] 并且在 printf() 中使用错误的签名会导致 UB [3]。
ISO/IEC 9899 中针对 C99 的相关引用
[1] 根据 C99 6.3.1.1:2 升级为int:
如果
int可以表示原始类型的所有值,则该值为 转换为int;否则,它将转换为unsigned int。 这些称为整数促销。所有其他类型都是 整数促销保持不变。
[2] 格式说明符 "%c" 需要 int 参数,C99 7.19.6.1:8 c:
如果不存在
l长度修饰符,则int参数将转换为unsigned char,然后写入结果字符。
[3] 在fprintf() (3) 中使用错误的类型,包括错误的签名,根据 C99 7.19.6.1:9 导致 UB:
... 如果任何参数不是对应的正确类型 转换规范,行为未定义。
va_arg 宏给出了具有不同符号的相同类型的例外,但printf() 没有,并且没有要求printf() 使用va_arg (4)。
脚注: (标有 (n))
-
这意味着
INT_MAX==SCHAR_MAX,因为char没有填充。 -
同样的规则适用于
printf(),参见 C99 7.19.6.3:2
【问题讨论】:
-
@einpoklum 如果没有促销,当
sizeof(int)>1(绝大多数系统)时,UB 会为"%c"提供char,因为%c期望int。格式说明符%c没有hh长度修饰符,因此您必须将其强制转换为int而无需提升。 -
@12431234123412341234123 :如果没有提升,
printf()将被写入,因此"%c"期望char。 -
@12431234123412341234123 你是对的。我忘记了这种可能性。
标签: c language-lawyer undefined-behavior integer-promotion