哪个代码是有效的?我在输出上得到零个字符,想知道这是否是由于将字符作为整数处理不当引起的,反之亦然。%c说明符是应该打印的,我只是不确定最后一个参数。
int c;
fprintf(stdout, "%c", c);
int n;
fprintf(stdout, "%c", n);
关于扫描的相同问题,应该是字符还是整数或两者之一?
两者都可以。ISO C11标准在7.21.6.1 The fprintf function /9
中规定(所有不同的*printf
和*scanf
调用均根据fprintf
和fscanf
定义(:
如果任何参数不是相应转换规范的正确类型,则行为未定义。
但是,在%c
(/8
(部分中,它还指出(我的强调(:
如果不存在
l
长度修饰符,则int
参数将转换为unsigned char
,并写入生成的字符。
事实上,传递int
或char
没有区别,因为默认参数提升是在省略号之外的 varargs 类型函数上执行的(根据6.5.2.2 Function calls /6
和/7
和6.3 Conversions
(
。对每个参数执行整数升级,类型为 float 的参数提升为双精度。这些称为默认参数升级。
函数原型声明器中的省略号表示法会导致参数类型转换在最后一个声明的参数之后停止。默认参数 升级是在尾随参数上执行的。
如果
int
可以表示原始类型的所有值(受位字段的宽度限制(,则该值将转换为 int;否则,它将转换为无符号 int。这些称为整数促销。
因此,由于fprintf
定义如下:
int fprintf(FILE * restrict stream, const char * restrict format, ...);
这意味着无论如何,char
参数都将升级为int
。
fscanf
是另一回事。它以7.21.6.2 The fscanf function /12
(再次强调(指出:
如果不存在
l
长度修饰符,则相应的参数应为 指向足够大的字符数组的初始元素以接受序列的指针。不添加空字符。
这意味着您应该提供字符(或字符数组(的地址。如果您提供了一个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
的其他字节保持不变(用....
表示(,导致int
的最终值不是0x36
。