union test
{
int i;
char ch;
}t;
int main()
{
t.ch=20;
}
假设sizeof(int)==2
并且为t分配的内存地址是2000,2001
然后在哪里存储20 {即t.ch
- 在2000年或2001年或取决于机器的字节顺序?
答案 0 :(得分:20)
C99标准(§6.7.2.1.14)说:
联合的大小足以包含其最大的成员。 at的值 大多数成员可以随时存储在union对象中。 指向a的指针 联合对象,适当转换,指向其每个成员 (或如果成员有点 - 字段,然后到它所在的单位),反之亦然。
(强调补充)
粗体声明实际上说联盟的每个成员都有相同的地址,所以他们都在同一地址“开始”。 t
与t.ch
一样t.i
应位于地址2000,因此t.ch
与t.i
的第一个字节(按地址顺序)重叠。
这意味着“在现实世界中设置t.i
之后,如果我尝试阅读t.c
,我会得到什么取决于平台的字节顺序,以及在尝试阅读根据C标准(§6.2.6.1.6/ 7,在§J.1.1中重述),在另一个中写入的联合是未指定的行为。
更有助于理解机器的字节顺序(至少,我认为它更容易理解)是有这样的联合:
union
{
int i;
unsigned char ch[sizeof(i)];
} t;
操作
t.i=20;
然后在t.ch
查看两个字符中的内容。如果您使用的是小端机器,则会获得t.ch[0]==20
和t.ch[1]==0
,如果您使用的是大端机器(如果sizeof(int)==2
)则相反。请注意,正如已经说过的,这是一个特定于实现的细节,标准甚至没有提到字节序。
为了使它更清晰:如果你有一个2字节的int
var设置为20,在小端机器上,按地址顺序转储与之关联的内存,你会得到(在十六进制表示,按空格分割的字节):
14 00
在大端机器上你会得到
00 14
从我们的观点来看,big-endian表示看起来“更正确”,因为在小端表示中,构成整个int
的字节以相反的顺序存储。
此外我说如果我这样做:
int a=20;
printf("%d",* (char*)&a);
那么输出是否依赖于字节序,即20是否存储在2000或2001?
是的,在这里确实如此,但在你的问题中,你在问另一件事;这看起来更像我的示例。
答案 1 :(得分:1)
test将占用两个字节,因此将在地址2000,2002等处分配。并且每个union实例的任何值都将从该基址开始存储。
联盟的每个成员都将存储在该联盟实例的同一地址中。这就是为什么你只能在一个联合中同时存储一种类型的值。因此,联合会占用最大成员所需的字节数。