#include <stdio.h>
int main() {
float a = 1234.5f;
printf("%d\n", a);
return 0;
}
它显示一个0
!! 那怎么可能?这是什么原因?
我故意%d
在printf
声明中加入,以研究的行为printf
。
Answers:
那是因为%d
期望一个,int
但是您提供了一个浮动。
使用%e
/ %f
/ %g
打印浮点数。
关于为什么打印0的原因:在将浮点数double
发送到之前将其转换为printf
。小尾数中双精度表示形式的数字1234.5为
00 00 00 00 00 4A 93 40
A %d
消耗32位整数,因此输出零。(作为测试,printf("%d, %d\n", 1234.5f);
您可以得到输出0, 1083394560
。)
至于为什么将6.5.2.2/7从printf的原型float
转换为,double
int printf(const char*, ...)
函数原型声明器中的省略号引起参数类型转换在最后声明的参数之后停止。默认参数提升是对尾随参数执行的。
从6.5.2.2/6开始,
如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并将具有该类型的参数
float
提升为double
。这些称为默认参数提升。
(感谢Alok找出这个问题。)
printf
是可变函数,并且标准说对于可变函数,a 在传递之前float
转换为double
。
printf()
调用未定义的行为。
从技术上讲是没有的 printf
,每个库实现了自己,因此,你的努力学习方法printf
做,你在做什么,是不是要多大用处的行为。您可能正在尝试研究printf
系统上的行为,如果是,则应阅读文档,并查看源代码以printf
了解库是否可用。
例如,在我的Macbook上,我1606416304
随程序一起输出。
话虽如此,当您将a传递float
给可变参数函数时,float
会作为传递double
。因此,您的程序等效于声明a
为double
。
要检查a的字节double
,您可以在SO上看到最近问题的答案。
让我们这样做:
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
unsigned char *p = (unsigned char *)&a;
size_t i;
printf("size of double: %zu, int: %zu\n", sizeof(double), sizeof(int));
for (i=0; i < sizeof a; ++i)
printf("%02x ", p[i]);
putchar('\n');
return 0;
}
当我运行上述程序时,我得到:
size of double: 8, int: 4
00 00 00 00 00 4a 93 40
因此,原来的前四个字节为double
0,这可能就是为什么将其0
作为printf
调用的输出。
为了获得更有趣的结果,我们可以对程序进行一些更改:
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
int b = 42;
printf("%d %d\n", a, b);
return 0;
}
当我在Macbook上运行上述程序时,我得到:
42 1606416384
在Linux机器上使用相同的程序,我得到:
0 1083394560
int
参数在不同的寄存器不是通过double
参数。 printf
with %d
接受int
参数42,第二%d
个int
参数可能会显示垃圾,因为没有第二个参数。
该%d
说明符告诉printf
期待一个整数。因此,float的前四个(或两个,取决于平台)字节被解释为整数。如果它们恰好为零,则打印零
1234.5的二进制表示形式类似于
1.00110100101 * 2^10 (exponent is decimal ...)
使用一个float
实际上表示为IEEE754双精度值的C编译器,字节将是(如果我没有记错的话)
01000000 10010011 01001010 00000000 00000000 00000000 00000000 00000000
在字节序很少的Intel(x86)系统上(即,最低有效字节排在最前面),该字节序列被反转,因此前四个字节为零。也就是说,什么printf
打印出来...
有关IEEE754的浮点表示,请参见此Wikipedia文章。
这是因为浮点数以二进制表示。转换为整数会使它保留为0。
因为您调用了未定义的行为:您对它的参数类型说谎,从而违反了printf()方法的约定,所以编译器可以自由地执行自己喜欢的任何事情。它可能会使程序输出“ dksjalk是一个ninnyhead !!!” 从技术上讲,这仍然是正确的。
嘿,它必须打印一些东西,所以它打印了0。请记住,在C 0中,其他所有内容!
不是整数。尝试使用%f
。