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

Why char specified as integer in printf gets printed correctly

为什么下面的代码有效?

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

打印出来:

65 - size: 1

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

只要在表达式中使用任何排名低于 int 的整数类型,它都会 提升 intunsigned int .这在 C 标准的第 6.3.1.1p2 节中指定:

The following may be used in an expression wherever an int or unsigned int may be used:

  • An object or expression with an integer type (other than int or unsigned int ) whose integer conversion rank is less than or equal to the rank of int and unsigned int .
  • A bit-field of type _Bool , int , signed int ,or unsigned int .

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int ; otherwise, it is converted to an unsigned int . These are called the integer promotions .

All other types are unchanged by the integer promotions

这就是本例中发生的情况,因为 printf 函数在编译时并不知道其参数的类型。所以char参数提升为int,用%d格式化才有效。

具有可变长度参数列表的函数有一条特殊规则,例如 printf。在参数列表的可变长度部分,所有小于 int 的整数参数被提升为 int,并且 float 被提升为 double。所以事实证明使用 %d.

打印字符(或 short)完全没问题

这些 默认参数提升 最终导致了 printf 中的一些异常情况。您可能认为 charshortintfloatdouble 的正确格式说明符是 %hhd%hd%d%f%lf。但实际上,您可以使用 %d%d%d%f%fprintf 基本上忽略了浮点数的 l 修饰符,而且它似乎忽略了整数的 h 修饰符。 (实际上 h 可以在模糊的情况下有所作为,正如 chux 在评论中解释的那样。)