为什么printf()没有输出这个整数作为浮点数?

时间:2014-12-18 09:44:30

标签: c windows printf stdio

我有这段代码:

#include <stdio.h>

int main()
{
    int i = 12345;
    printf("%f", i);

    return 0;
}

printf()将输出0.000000,不应该printf()将i中包含的位解释为浮点数吗?

8 个答案:

答案 0 :(得分:5)

这是技术上未定义的行为,因此任何事情都可能发生,例如@Art在他的回答中描述的内容。

因此,这里的答案解释了如果您尝试将12345打印为浮点数会发生什么情况,假设printf确实看到了正确的32位值。

让我们分析您试图表示的数字的二进制表示。

使用http://www.h-schmidt.net/FloatConverter/IEEE754.html我们可以看到十进制数12345具有以下32位表示:

decimal      12345
hexadecimal  0x00003039

将位到位转换为IEEE-754浮点32位值,这表示:

float        1.7299E-41

让我们尝试打印它:

#include <stdio.h>

int main() {
    printf("%f\n", 1.7299E-41);
    return 0;
}

打印:

0.000000

现在让我们阅读printf手册页,如下所示:http://linux.die.net/man/3/printf

  

f,F

     

double参数被舍入并在样式[ - ] ddd.ddd中转换为十进制表示法,其中小数点字符后面的位数等于精度规范。如果缺少精度,则取6;如果精度明确为零,则不显示小数点字符。如果出现小数点,则至少会出现一个数字。

1.7299E-41值无法使用此标志以默认精度表示,因此您获得的结果确实是正确的值。

答案 1 :(得分:5)

从技术上讲,这是未定义的行为

您应该使用联合执行此操作并使用%e而不是%f进行打印,因为它只是一个小数字:

#include <stdio.h>
union int2float
{
  int a;
  float b;
};

int main()
{
    union int2float tmp;
    tmp.a = 12345;

    printf("%e\n", tmp.b);

    return 0;
}

这会产生1.729903e-41

使用%.100f,您将获得0.0000000000000000000000000000000000000000172990295420898667405534417057140146406548336724655872023410作为输出。

答案 2 :(得分:2)

最有可能的原因printf并未将i中的位解释为浮点数,printf没有看到i at printf所有。我怀疑你正在运行x86_64或类似的平台,其中参数传递给寄存器中的函数。通常printf会将你的int解释为你给它的格式说明符。但是函数的浮点参数在x86_64上的处理方式不同,并且被放入不同的寄存器中。因此,输出为0的原因是printf拉出格式字符串后面的第一个浮点参数而不是第一个通用寄存器并打印出来。由于您在调用#include <stdio.h> int main(int argc, char **argv) { printf("%f\n", 17.42); printf("%f\n", 0x87654321); return 0; } 之前未使用任何浮点寄存器,因此很可能从程序启动时将其归零。

您可以尝试以下实验:

$ ./foo
17.420000
17.420000

我得到了这个输出:

printf

说了这么多,唯一正确的答案是:这是未定义的行为,不要这样做。但是看看幕后发生了什么很有意思。

如果你想深入研究它并在Linux / MacOS / * BSD上运行this document, section 3.2.3描述了如何将参数传递给函数(包括像printf这样的varargs函数)。 Windows做的事情略有不同,但在这种情况下,Windows上的结果将完全相同。 Linux / MacOS / * BSD上的%xmm0会在%xmm1 %rsi%rdx中调用时将printf({{1}}打印在论坛上)在Windows上。)

当然,如果我对x86_64错了,请忽略我所说的一切,并查看@SirDarius的答案,因为这适用于许多(特别是较旧的)架构。如果您使用的是alpha,sparc,powerpc,arm等,那么您自己就可以了。使用int调用{{1}}一次,使用float调用一次,反汇编编译的代码并查看参数的传递方式。

答案 3 :(得分:1)

如果要将int打印为float,请将其强制转换为:

printf("%f", (float)i);

答案 4 :(得分:1)

printf()在格式化字符串(及其计数)之后知道参数的数据类型的唯一方法是读取格式字符串。内存中整数的表示与浮点数不同。您以整数的格式传递printf()数据,但它采用浮点数的格式。这就是你在控制台中得到垃圾的原因。您可以通过类型转换来纠正此问题。

printf("%f", (float) i);

答案 5 :(得分:0)

使用%f格式说明符时,必须使用float变量并打印该值。 但是您已将i声明为整数并尝试使用%f进行打印,它会打印一些值。 因为它是一个整数,所以你必须使用%d说明符。 在printf %f中将搜索float变量。但是没有浮点变量,所以它会输出一些值。

您可以在打印时键入转换整数值。 printf("%f",(float)i);

答案 6 :(得分:0)

要将i设为float类型,您需要输入。

您可以使用

printf("%f", (float)i);

实施例

float myFloat;
int myInt; 
myFloat = (float)myInt ;        // Type casting

答案 7 :(得分:0)

试试这个

int i = 12345;
printf("%.2f", i/1.0f);