【问题标题】:GCC fprintf: should that be an int (32bit) or char (8bit)?GCC fprintf:应该是 int(32 位)还是 char(8 位)?
【发布时间】:2018-12-06 23:38:33
【问题描述】:

哪些代码有效?我在输出上得到零个字符,并想知道这是否是由于将字符作为整数处理不当引起的,反之亦然。 %c 说明符是应该打印的,我只是不确定最后一个参数。

int c;
fprintf(stdout, "%c", c);
int n;
fprintf(stdout, "%c", n);

关于scanf的同样问题,应该是char还是int?

【问题讨论】:

  • %c 用于字符。
  • @tkausl %c%d 都以int 作为输入,它们的输出不同
  • 您是在问c 的有效值范围是多少?
  • 如果您对某些代码有疑问,请发布MCVE
  • @tkausl: "%c 用于字符" -- 这有点误导。 %c 需要 int 参数并将其值打印为字符。如果您传递 char 参数,它将被提升为 int

标签: c gcc printf scanf


【解决方案1】:

两个都好。 ISO C11 标准在7.21.6.1 The fprintf function /9 中声明(所有各种*printf*scanf 调用都是根据fprintffscanf 定义的):

如果任何参数不是相应转换规范的正确类型,则行为未定义。

但是,在%c (/8) 的部分中,它还指出(我的重点):

如果不存在 l 长度修饰符,则 int 参数将转换为 unsigned char,并写入结果字符。

事实上,传递intchar 并没有什么区别,因为默认参数提升是在椭圆之外的可变参数类型函数上执行的(根据6.5.2.2 Function calls /6/76.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
+------+------+------+------+

您可以看到intother 字节保持不变(由.... 表示),导致int 的最终值是other em> 比0x36.

【讨论】:

    猜你喜欢
    • 2015-08-03
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 2011-03-08
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多