工会成员如何存储?

union test { int i; char ch; }t; int main() { t.ch=20; } 

假设sizeof(int)==2并且为t分配的内存地址是2000,2001。
然后在哪里20即t.ch存储 – 在2000年或2001年或取决于机器的字节顺序?

C99标准(§6.7.2.1.14)说:

联合的大小足以包含其最大的成员。 最多一个成员的值可以随时存储在union对象中。 指向适当转换的并集对象的指针指向其每个成员 (或者如果成员是位字段,则指向它所在的单位),反之亦然。

(重点补充)

粗体声明实际上说联盟的每个成员都有相同的地址,所以他们都在同一地址“开始”。 t ,如t.chti ,应该在地址2000,因此t.chti的第一个字节(以地址顺序)重叠。

在现实世界中,如果我在设置tc之后尝试读取ti ,我会得到什么?这意味着什么取决于平台的字节顺序,并且当你在另一个中写入时试图读取一个联合成员的事实是未指定的行为根据C标准(§6.2.6.1.6/ 7,重述于§J.1.1)。


什么有助于理解机器的字节顺序(至少,我认为它更直接理解)是有这样的联合:

 union { int i; unsigned char ch[sizeof(i)]; } t; 

 ti=20; 

然后在t.ch看两个字符里面的t.ch 。 如果你使用的是小端机器,你会得到t.ch[0]==20t.ch[1]==0 ,如果你使用的是大端机器(如果是sizeof(int)==2 )。 请注意,正如已经说过的,这是一个特定于实现的细节,标准甚至没有提到字节序。

为了使它更清晰:如果你有一个2字节的int var设置为20,在little-endian机器上,以地址顺序转储与它相关的内存,你将得到(以hex表示,按空格分割的字节) ):

 14 00 

而在大端机器上,你会得到

 00 14 

从我们的观点来看,big-endian表示看起来“更正确”,因为在小端表示中,构成整个int的字节以相反的顺序存储。


而且我说如果我这样做:

 int a=20; printf("%d",* (char*)&a); 

然后输出不依赖于endian-ness,即20是存储在2000还是2001?

是的,在这里确实如此,但在你的问题中,你会问另一件事; 这看起来更像我的榜样。

test将占用两个字节,因此将在地址2000,2002等处分配。并且每个联合实例的任何值都将从该基地址开始存储。

联盟的每个成员都将存储在该联合实例的同一地址中。 这就是为什么你只能在一个联合中同时存储一种类型的值。 因此,联合会占用最大成员所需的字节数。