使用%f打印整数变量

Pra*_*eek 7 c

以下c程序的输出是:0.000000输出后面是否有逻辑或者是编译器依赖的答案还是我只是得到垃圾值?

#include<stdio.h>

int main()
{
    int x=10;
    printf("%f", x);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

chr*_*ris 7

从最新的C11草案:

§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 unde?ned, 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.
Run Code Online (Sandbox Code Playgroud)


Kei*_*son 7

要记住的最重要的事情是,正如克里斯指出的那样,行为是未定义的。如果这是在一个真实的程序中,唯一明智的做法就是修复代码。

另一方面,查看行为未由语言标准定义的代码的行为可能具有指导意义(只要您小心不要过多地概括该行为)。

printf"%f"格式需要一个 type 参数double,并以没有指数的十进制形式打印它。非常小的值将打印为0.000000.

当你这样做时:

int x=10;
printf("%f", x);
Run Code Online (Sandbox Code Playgroud)

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

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

因此,该调用将(可能)将该int10作为 4 字节的数量推入堆栈,并将从堆栈中printf取出 8 字节的数据并将其视为 a 的表示double。4 个字节将是10(以十六进制表示0x0000000a);其他 4 个字节将是垃圾,很可能为零。垃圾可能是 8 字节数量的高位或低位 4 字节。(或其他任何东西;记住行为是未定义的。)

这是我刚刚拼凑的一个演示程序。它不是滥用printf,而是使用将int对象的表示复制到double对象中memcpy()

#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;
}
Run Code Online (Sandbox Code Playgroud)

我的 x86 系统上的输出是:

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
Run Code Online (Sandbox Code Playgroud)

如您所见, 的值double非常小(有关详细信息,您可以查阅有关 IEEE 浮点格式的参考资料),接近于零以将其"%f"打印为0.000000.

让我再次强调,行为是 undefined,这具体意味着语言标准对程序的行为“没有要求”。字节顺序、浮点表示和参数传递约定的变化可以显着改变结果。甚至编译器优化也会影响它;允许编译器假设程序的行为是明确定义的,并基于该假设执行转换。

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