0

我想了解更多关于类型双关和别名的信息。因此,我在选项中使用GCC 文档-fstric-aliasing提供的代码,如下所示:

union a_union{
    int i;
    double d;
};

int f(){
    union a_union t;
    t.d=3.0;

    return t.i
}

/*what I add*/
int main(int argc, char *argv[])
{
    printf("%d\n",f());
    return 0;
}

我期望没有什么特别的,但我只得到 0。所以我用不同的值进行测试,t.d但没有变化。我在 Debian 9 上使用 gcc 6.3 测试此代码,没有选项。我也尝试使用-fno-strict-aliasing相同的选项

如果有人可以解释,为什么我只得到 0 那就太好了

4

3 回答 3

2

这取决于您的特定处理器使用的存储类型。

3.0000000000000000(双精度 3)由 4008 0000 0000 0000(十六进制)表示

您的处理器可以按各种顺序存储浮点数,其中一些首先存储最低有效字节/字。在这种情况下,int 只会返回 0000 0000。

尝试使用 Pi 或 sqrt(2)

于 2019-11-20T17:16:01.440 回答
1

成员的大小在任何常见系统中都不匹配。int现在通常是 32 位和double64 位。由于采用小端存储,末尾的零位3.0000000000对应于int成员的零位。

试试这个:

#include <inttypes.h>
#include <stdio.h>

union q_union{
    uint64_t i;
    double d;
};

_Static_assert(sizeof (union q_union){}.i == sizeof (union q_union){}.d,
     "The sizes of double and uint64_t must match");

uint64_t f(void) {
    union q_union t;
    t.d = 3.0;
    return t.i;
}

int main(int argc, char *argv[])
{
    printf("%" PRIu64 "\n", f());
    printf("%#" PRIx64 "\n", f());
    return 0;
}

输出:

4613937818241073152
0x4008000000000000
于 2019-11-20T17:27:06.183 回答
0

A doublewith value3.0有很多 0 字节。我假设你的机器的字节序是这样的,它们与 int 重叠。如果不是3.0您使用3.1,您应该看到另一个值。

代替 an int,您也可以尝试使用 an unsigned long long,它通常具有与 double 相同的大小,您将能够打印其整个表示。

于 2019-11-20T17:14:56.920 回答