工会成员如何存储?

时间:2010-12-27 17:52:01

标签: c endianness unions

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

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

2 个答案:

答案 0 :(得分:20)

C99标准(§6.7.2.1.14)说:

  

联合的大小足以包含其最大的成员。 at的值    大多数成员可以随时存储在union对象中。 指向a的指针   联合对象,适当转换,指向其每个成员 (或如果成员有点 -   字段,然后到它所在的单位),反之亦然。

(强调补充)

粗体声明实际上说联盟的每个成员都有相同的地址,所以他们都在同一地址“开始”。 tt.ch一样t.i应位于地址2000,因此t.cht.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]==20t.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实例的任何值都将从该基址开始存储。

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