工会不重新诠释价值观吗?

Dar*_*tom 9 c floating-point precision long-double unions

考虑以下程序:

#include <stdio.h>

union myUnion
{
    int x;
    long double y;
};

int main()
{
    union myUnion a;
    a.x = 5;
    a.y = 3.2;
    printf("%d\n%.2Lf", a.x, a.y);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

-858993459
3.20
Run Code Online (Sandbox Code Playgroud)

很好,因为该int成员使用该成员的某些位进行解释long double。但是,相反实际上并不适用:

#include <stdio.h>

union myUnion
{
    int x;
    long double y;
};

int main()
{
    union myUnion a;
    a.y = 3.2;
    a.x = 5;
    printf("%d\n%.2Lf", a.x, a.y);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

5
3.20
Run Code Online (Sandbox Code Playgroud)

问题是,为什么long double不将它们重新解释为某个垃圾值(因为其字节中的4个应表示整数)?这不是巧合,程序针对的所有值输出3.20 a.x,而不仅仅是5。

Kaz*_*Kaz 7

但是,反向并不真正适用

在小端序系统上(多字节值的最低有效字节在最低地址),int对应于的尾数的最低有效位long double。您必须long double非常精确地打印出来,才能看到它对int那些无关紧要的数字的影响。

在大型字节序系统(如Power PC盒)上,情况会有所不同:该int部分将与的最高有效部分long double对齐,与符号位,指数和最高有效尾数位重叠。因此x,即使只打印了几个有效数字,的变化也会对观察到的浮点值产生巨大影响。但是,对于的较小值x,该值似乎为零。

在PPC64系统上,以下版本的程序:

int main(void)
{
    union myUnion a;
    a.y = 3.2;
    int i;
    for (i = 0; i < 1000; i++) {
      a.x = i;
      printf("%d -- %.2Lf\n", a.x, a.y);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

只打印什么

1 -- 0.0
2 -- 0.0
[...]
999 - 0.0
Run Code Online (Sandbox Code Playgroud)

这是因为我们正在创建一个全零的指数字段,从而使值接近零。但是,初始值3.2完全被破坏了。它不仅仅消除了其最低有效位。


Moh*_*ain 6

的大小long double非常大。要查看修改x字段对在通过via进行修改时不影响x尾数y和其他联合位的LSB对齐的实现的影响x,您需要以更高的精度打印该值

  • 在C语言中,*不一定*未定义。引用的问题中的可接受答案表示允许这样做,尽管它可能是陷阱表示。如果不是陷阱表示,则结果定义良好。 (2认同)