#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中编译了这个程序。
答案 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 ,您会再次看到您的字节,此外它是未定义的行为和部分它取决于程序运行平台的内存架构。