描述这个工会发生了什么

Describe what's happening with this union

一位朋友向我展示了他在 class 中必须做的多项选择题练习,他知道正确答案是什么,但他并不真正理解给定代码中发生的原因或内容。

在这里(假设我没有任何错误地输入):

What does the following code display ?

typedef union{
  long adr;
  struct{
     unsigned char a,b,c,d,e;
  }x;
}Ip;
static Ip y;
printf("%l2ld | %02X.%02X.%02X.%02X.%02X\n",
       y.adr,y.x.a,y.x.b,y.x.c,y.x.d,y.x.e);
y.adr=1234567890;
printf("%l2ld | %02X.%02X.%02X.%02X.%02X\n",
       y.adr,y.x.a,y.x.b,y.x.c,y.x.d,y.x.e);
y.x.a='A';y.x.b='B';y.x.c='C';y.x.d='D';y.x.e='E';
printf("%l2ld | %02X.%02X.%02X.%02X.%02X\n",
       y.adr,y.x.a,y.x.b,y.x.c,y.x.d,y.x.e);

Answers (?? means a random value) :

A)
         0 | 00.00.00.00.00
1234567890 | 00.00.00.00.00
1234567890 | 41.42.43.44.45

B)
         0 | 00.00.00.00.00
1234567890 | ??.??.??.??.??
?????????? | 41.42.43.44.45

C)
?????????? | ??.??.??.??.??
1234567890 | ??.??.??.??.??
1234567890 | 41.42.43.44.45

D) Something else

现在,他得到了正确答案,即 B,但他不明白为什么,并说他本以为 C 是正确答案。不幸的是,我也不确定这里发生了什么。有人可以向我们详细说明这段代码的作用并帮助我们理解答案吗?提前致谢!

正确答案是A。

第一个printfy还没有初始化。因为它是 static 它是 zeo.

第二次 printf y.adr 被初始化,但成员没有。由于它们是全局的,因此它们为零。

第三次printf,一切都已初始化。 42 是 ASCII 的十六进制 B

答案可以选择B*ystatic 合格的,因此它的成员(最大字节:adr)将用 0 初始化。

赋值后y.adr=1234567890;adr会变成1234567890。结构成员的成员值将取决于数字 1234567890 中的字节数。根据 endianness 的不同,输出会有所不同。 考虑到小字节序,输出将是
1234567890 在二进制中是 1001001 10010110 00000010 11010010

的十六进制等效值
 01001001 => 49
 10010110 => 96
 00000010 => 02  
 11010010 => D2  

与第三个printf类似,ascii字符的十进制等价物

'A' => 01000101 
'B' => 01000100 
'C' => 01000011 
'D' => 01000010 
'E' => 01000001   

组合 01000101 01000100 01000011 01000010 01000001 是等同于 297498001985 的十进制。


假设:具有小端硬件的 64 位机器。

老实说,我认为这是一个误导性的问题。变量被声明为静态的事实是初始值为 0 的原因。静态变量在运行时被初始化为 0。这消除了 C.

答案的问题(以及让我摸不着头脑的问题)是 B 中的 ? 不是随机数。它们完全由存储在 adr 或 a-e 中的内容决定。如果您不了解它们的来源,它们看起来就像是乱码。

在联合中,所有变量在内存中共享相同的地址 space。在这种情况下,adr 和 struct x 在内存中共享 space。因此,当您更改其中一个的值时,它会更改另一个的值。

因此,如果将 adr 设置为 1234567890,则同时设置了 a 到 e 的值。它们将是恰好与代表 adr 的 long 部分对齐的任何字节。

同样,如果您设置 a-e,它会 "corrupt" adr 的值并更改显示的内容。