是的,printf
with"%c"
需要一个int
论点——或多或少。
如果参数的类型比 窄int
,那么它将被提升。在大多数情况下,促销是 to int
,具有明确定义的行为。在极少数情况下,plainchar
是无符号的并且sizeof (int) == 1
(这意味着CHAR_BIT >= 16
),一个char
参数被提升为unsigned int
,这可能导致未定义的行为。
字符常量已经是 type int
,因此printf("%c", 'x')
即使在外来系统上也有很好的定义。(题外话:在 C++ 中,字符常量的类型是char
。)
这:
unsigned int foo = 42;
fprintf(fp, "%c\n", foo);
严格来说有未定义的行为。 N1570 7.1.4p1 说:
如果函数的参数具有......具有可变数量参数的函数不期望的类型(提升后),则行为未定义。
fprintf
电话显然与此相冲突。(感谢 ouah 指出这一点。)
另一方面,6.2.5p6 说:
对于每个有符号整数类型,都有一个对应的(但不同的)无符号整数类型(用关键字
unsigned指定),它使用相同的存储量(包括符号信息)并具有相同的对齐要求。
和 6.2.5p9 说:
有符号整数类型的非负值范围是对应无符号整数类型的子范围,相同值在每种类型中的表示是相同的。
带脚注:
相同的表示和对齐要求意味着作为函数的参数、函数的返回值和联合成员的可互换性。
脚注说函数参数类型int
和unsigned int
是可互换的,只要值在两种类型的可表示范围内。(对于典型的 32 位系统,这意味着该值必须在 0 到 2 31 -1 的范围内;int
从 -2 31到 -1 的unsigned int
值,以及从 2 31到 2 32 -1 的值超出范围其他类型,不可互换。)
但是 C 标准中的脚注是非规范性的。它们通常旨在澄清规范性文本中陈述的要求,而不是强加新的要求。但是这里的规范文本只是说明相应的有符号和无符号类型具有相同的表示形式,这并不一定意味着它们以与函数参数相同的方式传递。原则上,编译器可以忽略该脚注,例如,在不同的寄存器中传递int
和参数,从而导致未定义。unsigned int
fprintf(fp, "%c\n", foo);
但在实践中,实现没有理由玩这种游戏,您可以依靠它fprintf(fp, "%c\n", foo);
按预期工作。我从未见过或听说过它不起作用的实现。
就个人而言,我不喜欢依赖它。如果我正在编写该代码,我会通过强制转换添加显式转换,这样一开始就不会出现这些问题:
unsigned int foo = 42;
fprintf(fp, "%c\n", (int)foo);
或者我会首先做foo
一个int
。