联盟概念中的混乱

时间:2012-07-07 07:06:24

标签: c++ c unions

#include<stdio.h>

union node {
     int i;
     char c[2];
};

main() {

    union node n;
    n.c[0] = 0;
    n.c[1] = 2;
    printf("%d\n", n.i);
    return 0;
}

我认为它给出512输出因为第一个字节中的c [0]值存储而第二个字节中存储了c [1]值,但是给出了1965097472。为什么? 我在windows中的codeblocks中编译了这个程序。

5 个答案:

答案 0 :(得分:8)

你的联盟分配了四个字节,从:

开始
[????] [????] [????] [????]

您设置了至少两个重要字节:

[????] [????] [0x02] [0x00]

然后将所有四个字节打印为整数。你一定不会得到512,因为任何东西都可能在那些最重要的两个字节中。在这种情况下,你有:

[0x75] [0x21] [0x02] [0x00]

答案 1 :(得分:3)

因为未定义的行为。访问未设置的union成员就是这么简单的。它可以做任何事情,打印任何东西,甚至崩溃。

答案 2 :(得分:1)

未定义的行为是......未定义。

我们可以尝试回答为什么给出特定结果 (其他答案通过猜测编译器实现细节来做到这一点),但我们不能说为什么另一个结果不是给出。对于我们所知道的一切,编译器可以打印0,格式化您的硬盘,让您的房子着火或将100,000,000美元转移到您的银行账户。

答案 3 :(得分:0)

请注意,您的int可能至少有4个字节(不是2个字节,就像在好日子里一样)。要让尺寸匹配,请将i的类型更改为uint16_t

即使在此之后,标准也不会真正允许设置一个联合成员,然后访问另一个联盟成员以尝试重新解释字节。但是,您可以使用reinterpret_cast获得相同的效果。

union node {
    uint16_t i;
    uint8_t c[2];
};

int main() {
    union node n;
    n.c[0] = 0;
    n.c[1] = 2;
    std::cout << *reinterpret_cast<uint16_t *>(&n) << std::endl;
    return 0;
}

答案 4 :(得分:0)

int编译为32位数字,小端。通过将两个较低的字节分别设置为2和0然后读取int得到1965097472.如果查看十六进制表示7521 0200 ,您会再次看到您的字节,此外它是未定义的行为和部分它取决于程序运行平台的内存架构。