了解printf的隐式转换

C99标准区分隐式和显式类型转换(6.3转换)。 我猜,但是无法找到,当目标类型的精度高于源时,会执行隐式强制转换,并且可以表示其值。 [这是我认为从INT到DOUBLE发生的事情]。 鉴于此,我看下面的例子:

#include  // printf #include  // for INT_MIN #include  // for endianess #define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100) int main() { printf("sizeof(int): %lu\n", sizeof(int)); printf("sizeof(float): %lu\n", sizeof(float)); printf("sizeof(double): %lu\n", sizeof(double)); printf( IS_BIG_ENDIAN == 1 ? "Big" : "Little" ); printf( " Endian\n" ); int a = INT_MIN; printf("INT_MIN: %i\n", a); printf("INT_MIN as double (or float?): %e\n", a); } 

我很惊讶地发现输出:

 sizeof(int): 4 sizeof(float): 4 sizeof(double): 8 Little Endian INT_MIN: -2147483648 INT_MIN as double (or float?): 6.916919e-323 

因此,打印的浮点值是非常小的正常正双倍4.9406564584124654×10 ^ -324附近的次正规浮点数。 当我为了endianess注释掉两个printf时发生了奇怪的事情,我得到了double的另一个值:

 #include  // printf #include  // for INT_MIN #include  // for endianess #define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100) int main() { printf("sizeof(int): %lu\n", sizeof(int)); printf("sizeof(float): %lu\n", sizeof(float)); printf("sizeof(double): %lu\n", sizeof(double)); // printf( IS_BIG_ENDIAN == 1 ? "Big" : "Little" ); printf( " Endian\n" ); int a = INT_MIN; printf("INT_MIN: %i\n", a); printf("INT_MIN as double (or float?): %e\n", a); } 

输出:

 sizeof(int): 4 sizeof(float): 4 sizeof(double): 8 INT_MIN: -2147483648 INT_MIN as double (or float?): 4.940656e-324 
  • gcc –version:(Ubuntu 4.8.2-19ubuntu1)4.8.2
  • uname:x86_64 GNU / Linux
  • 编译器选项其中:gcc -ox xc -Wall -Wextra -std = c99 –pedantic
  • 是的,有一个警告:
 xc: In function 'main': xc:15:3: warning: format '%e' expects argument of type 'double', but argument 2 has type 'int' [-Wformat=] printf("INT_MIN as double (or float?): %e\n", a); ^ 

但我仍然无法理解究竟发生了什么。

  • 在小的endianess我认为MIN_INT为:00 … 0001和MIN_DBL(Subnormal)为100..00#,从尾数开始,然后是指数,以#作为符号位结束。
  • 这种在int上应用“%e”格式说明符的forms是隐式转换吗?是重新解释转换?

我迷路了,请让我高兴。

 printf("INT_MIN as double (or float?): %e\n", a); 

以上行有问题您无法使用%e打印整数。 行为未定义。

你应该用

 printf("INT_MIN as double (or float?): %e\n", (double)a); 

要么

 double t = a; printf("INT_MIN as double (or float?): %e\n", t); 

相关文章 :这篇文章解释了如何在printf中使用不正确的打印说明符导致UB。

va_arg函数的参数没有被转换,语法上编译器对这些函数的参数一无所知,所以他不能这样做。 现代编译器确实知道解释格式字符串,因此他们能够在发生可疑事情时向您发出警告。 当你看到gcc的警告时,就会发生这种情况。

更确切地说,对于整数类型有一些促销,它们被提升为int ,而对于被提升为double float 。 但这就是所有可能发生的魔法。

总之,始终使用正确的格式说明符。

顺便说一句,对于你的sizeof表达式的size_t ,正确的是%zu