#include <stdio.h>
int main() {
float a = 1234.5f;
printf("%d\n", a);
return 0;
}
它显示一个0
!! 这怎么可能?原因是什么?
我特意%d
在printf
语句中放了一个来研究printf
.
#include <stdio.h>
int main() {
float a = 1234.5f;
printf("%d\n", a);
return 0;
}
它显示一个0
!! 这怎么可能?原因是什么?
我特意%d
在printf
语句中放了一个来研究printf
.
那是因为%d
期望一个int
但你提供了一个浮点数。
使用%e
//打印浮点数%f
。%g
关于为什么打印 0:浮点数double
在发送到之前转换为printf
. little endian 中双重表示的数字 1234.5 是
00 00 00 00 00 4A 93 40
A%d
消耗一个 32 位整数,因此打印一个零。(作为测试,你可以printf("%d, %d\n", 1234.5f);
输出0, 1083394560
。)
至于为什么float
要转换成double
,因为printf的原型是int printf(const char*, ...)
,从6.5.2.2/7开始,
函数原型声明器中的省略号会导致参数类型转换在最后一个声明的参数之后停止。默认参数提升是在尾随参数上执行的。
从 6.5.2.2/6 开始,
如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并将具有类型的参数
float
提升为double
. 这些被称为默认参数提升。
(感谢 Alok 发现这一点。)
从技术上讲,没有, printf
每个库都实现了自己的,因此,您尝试printf
通过做您正在做的事情来研究 的行为的方法不会有太大用处。您可能正在尝试研究printf
系统上的行为,如果是这样,您应该阅读文档,并查看源代码printf
是否可用于您的库。
例如,在我的 Macbook 上,我1606416304
通过您的程序获得输出。
话虽如此,当您将 a 传递float
给可变参数函数时, thefloat
将作为 a 传递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
说明%d
符告诉printf
期望一个整数。因此,浮点数的前四个(或两个,取决于平台)字节被解释为整数。如果它们恰好为零,则打印零
1234.5 的二进制表示类似于
1.00110100101 * 2^10 (exponent is decimal ...)
使用实际上表示为 IEEE754 双值的 C 编译器float
,字节将是(如果我没记错的话)
01000000 10010011 01001010 00000000 00000000 00000000 00000000 00000000
在字节顺序很小的 Intel (x86) 系统上(即最不重要的字节首先出现),此字节序列被反转,因此前四个字节为零。也就是说,printf
打印出来的...
有关根据 IEEE754 的浮点表示,请参阅此 Wikipedia 文章。
因为你调用了未定义的行为:你违反了 printf() 方法的约定,因为它在参数类型上撒谎,所以编译器可以随意做任何事情。它可以使程序输出“dksjalk is a ninnyhead!!!” 从技术上讲,它仍然是正确的。
这是因为浮点数以二进制表示。转换为整数后,其值为 0。
原因是这printf()
是一个非常愚蠢的功能。它根本不检查类型。如果您说第一个参数是 an int
(这就是您所说的%d
),它相信您并且它只需要 an 所需的字节int
。在这种情况下,假设您的机器使用 4 字节int
和 8 字节double
(float
转换为double
inside printf()
), 的前四个字节a
将只是零,并且会打印出来。
它不会自动将浮点数转换为整数。因为两者都有不同的存储格式。因此,如果要转换,请使用 (int) 类型转换。
#include <stdio.h>
int main() {
float a = 1234.5f;
printf("%d\n", (int)a);
return 0;
}
由于您也使用 C++ 对其进行了标记,因此此代码会按照您的预期进行转换:
#include <iostream.h>
int main() {
float a = 1234.5f;
std::cout << a << " " << (int)a << "\n";
return 0;
}
输出:
1234.5 1234
您只需将适当的格式说明符(%d、%f、%s 等)与相关数据类型(int、float、string 等)一起使用。
它不是一个整数。尝试使用%f
.
你想要 %f 而不是 %d
嘿,它必须打印一些东西,所以它打印了一个 0。记住在 C 中 0 是其他一切!