为什么在printf中指定为整数的char可以正确打印

时间:2018-10-23 19:44:05

标签: c types type-conversion printf stdio

以下代码为何起作用?

char c = 'A';
printf("%d - size: %d", c, sizeof(c));

打印出:

65 - size: 1

为什么输出不是垃圾,因为int通常为4个字节长,我们可以清楚地看到char为1个字节长。 编译器会进行隐式对话吗?

2 个答案:

答案 0 :(得分:5)

任何在表达式中使用的排名低于int的整数类型都会被提升intunsigned int。 C标准的6.3.1.1p2部分对此进行了规定:

  

以下表达式可以在表达式中使用int或unsigned   可以使用int:

     
      
  • 具有整数类型(小于int或unsigned int)的整数转换等级小于的对象或表达式   或等于int和unsigned int的等级。
  •   
  • 一个类型的位域   _Bool,int,signed int或unsigned int。
  •   
     

如果一个int可以表示原始类型的所有值(如   受宽度限制(对于位字段),该值为   转换为一个int;否则,它将转换为无符号   诠释这些称为整数促销。

     

所有其他类型的整数促销均不变

在这种情况下就是这种情况,因为printf函数在编译时并不隐式知道其参数的类型。因此,char参数被提升为int,并且使用%d对其进行格式化是有效的。

答案 1 :(得分:5)

对于带有可变长度参数列表的函数(例如printf)有一条特殊规则。在参数列表的变长部分中,所有小于int的整数参数都提升为int,而float提升为double。因此,事实证明,使用short打印字符(或%d)是非常好的。

这些默认参数提升最终导致了printf中的许多异常。您可能会认为charshortintfloatdouble的正确格式说明是%hhd,{{1} },%hd%d%f。但是实际上,您可以摆脱%lf%d%d%d%f的束缚。 %f基本上忽略了浮点数的printf修饰符,而似乎忽略了整数的l修饰符。 (实际上,h可以在晦涩的情况下有所作为,就像chux在评论中解释的那样。)