使用%f打印整数变量

问题描述 投票:7回答:6

以下c程序的输出是:0.000000

输出背后是否存在逻辑,或者答案编译器是否相关,或者我只是获得垃圾值?

#include<stdio.h>

int main()
{
    int x=10;
    printf("%f", x);
    return 0;
}

PS:-我知道尝试使用%f打印整数值是愚蠢的。我只是从理论角度提出这个问题。

c format-specifiers
6个回答
7
投票

从最新的C11 draft

§7.16.1.1/ 2

...if type is not compatible with the type of the actual next argument 
(as promoted according to the default argument promotions), the behavior 
is undefined, except for the following cases:

— one type is a signed integer type, the other type is the corresponding 
unsigned integer type, and the value is representable in both types;
— one type is pointer to void and the other is a pointer to a character type.

5
投票

最要记住的是,正如克里斯指出的那样,行为是不确定的。如果这是在真实程序中,则唯一明智的做法是修复代码。

另一方面,查看其行为未由语言标准定义的代码的行为可能是有启发性的(只要注意不要过多地泛化行为即可。)

printf"%f"格式需要类型为double的参数,并以没有指数的十进制形式打印它。很小的值将打印为0.000000

执行此操作时:

int x=10;
printf("%f", x);

我们可以根据您所使用的平台的一些假设来解释可见的行为:

  • int是4个字节
  • double是8个字节
  • [intdouble参数使用相同的机制传递到printf,可能是在堆栈上

因此,调用将(可能)将int10作为4字节的数量压入堆栈,并且printf将从堆栈中抓取8个字节的数据并将其视为[[ C0]。 4个字节将表示double(以十六进制表示10);其他4个字节将是垃圾,很可能为零。垃圾可以是8字节数量的高4字节或低4字节。 (或其他任何内容;请记住,行为是未定义的。)

这是我刚刚放在一起的演示程序。它不会滥用0x0000000a,而是使用printfint对象的表示复制到double对象中。

memcpy()

我的x86系统上的输出是:

#include <stdio.h>
#include <string.h>

void print_hex(char *name, void *addr, size_t size) {
    unsigned char *buf = addr;
    printf("%s = ", name);
    for (int i = 0; i < size; i ++) {
        printf("%02x", buf[i]);
    }
    putchar('\n');
}

int main(void) {
    int i = 10;
    double x = 0.0;
    print_hex("i (set to 10)", &i, sizeof i);
    print_hex("x (set to 0.0)", &x, sizeof x);

    memcpy(&x, &i, sizeof (int));
    print_hex("x (copied from i)", &x, sizeof x);
    printf("x (%%f format) = %f\n", x);
    printf("x (%%g format) = %g\n", x);

    return 0;
}

如您所见,i (set to 10) = 0a000000 x (set to 0.0) = 0000000000000000 x (copied from i) = 0a00000000000000 x (%f format) = 0.000000 x (%g format) = 4.94066e-323 的值非常小(有关详细信息,您可以查阅IEEE浮点格式的参考),足够接近零,以使double将其打印为"%f"

让我再次强调行为是未定义的

,这专门意味着语言标准对程序的行为“不施加任何要求”。字节顺序,浮点表示形式和参数传递约定的变化会极大地改变结果。即使编译器优化也会影响它。允许编译器假定程序的行为已得到良好定义,并根据该假设执行转换。

所以

随意忽略我在这里写的所有内容(第一和最后一段除外)。

1
投票

因为二进制中的整数10看起来像这样:


1
投票

结果未定义。


0
投票

基本上是垃圾。小整数看起来像不规范的浮点数,不应该存在。


0
投票

您可以像这样强制转换int变量:

© www.soinside.com 2019 - 2024. All rights reserved.