两个都好。 ISO C11 标准在7.21.6.1 The fprintf function /9 中声明(所有各种*printf 和*scanf 调用都是根据fprintf 和fscanf 定义的):
如果任何参数不是相应转换规范的正确类型,则行为未定义。
但是,在%c (/8) 的部分中,它还指出(我的重点):
如果不存在 l 长度修饰符,则 int 参数将转换为 unsigned char,并写入结果字符。
事实上,传递int 或char 并没有什么区别,因为默认参数提升是在椭圆之外的可变参数类型函数上执行的(根据6.5.2.2 Function calls /6 和/7 和6.3 Conversions)
... 对每个参数执行整数提升,浮点类型的参数提升为双精度。这些称为默认参数提升。
函数原型声明器中的省略号符号导致参数类型转换在最后一个声明的参数之后停止。 默认参数
提升是在尾随参数上执行的。
如果int 可以表示原始类型的所有值(受宽度限制,对于位域),该值将转换为 int; strong> 否则,将其转换为无符号整数。这些称为整数促销。
所以,既然fprintf 是这样定义的:
int fprintf(FILE * restrict stream, const char * restrict format, ...);
这意味着char 参数无论如何都会升级为int。
fscanf 是另一回事。它在7.21.6.2 The fscanf function /12 中声明(再次强调):
如果不存在l 长度修饰符,则相应的参数应为
指向 character 数组的初始元素的指针,该数组大到足以接受序列。不添加空字符。
这意味着您应该提供一个字符(或字符数组)的地址。如果您提供int 并且它的大小不同,您可能会看到int 的部分 已更改,其余部分将保留为任意值。例如,在八位字节、四字节int、大端系统上:
+------+------+------+------+
| 0x12 | 0x34 | 0x56 | 0x78 | <- Initial value of int 0x12345678
+------+------+------+------+
| 0x36 | .... | .... | .... | <- Read character '6' (0x36 in ASCII)
+------+------+------+------+
| 0x36 | 0x34 | 0x56 | 0x78 | <- Final value of int 0x36345678
+------+------+------+------+
您可以看到int 的other 字节保持不变(由.... 表示),导致int 的最终值是other em> 比0x36.