描述这个联盟发生的事情

时间:2015-11-05 18:44:40

标签: c struct unions

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

这是(假设我输入没有任何错误):

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是正确的答案。不幸的是,我不确定这里发生了什么。有人可以给我们详细分析这些代码的作用并帮助我们理解答案吗?提前谢谢!

3 个答案:

答案 0 :(得分:2)

答案可能是选择B * ystatic限定的,因此其成员(具有最大字节:adr)将使用0进行初始化。

作业y.adr=1234567890;后,adr将为1234567890。 struct成员的成员值取决于数字1234567890中的字节数。根据{{​​3}},输出会有所不同。 以小尾数来计算输出将是
二进制文件中的12345678901001001 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位计算机。

答案 1 :(得分:2)

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

答案的问题(以及让我摸不着头脑的一段时间)是B中的?不是随机数。它们完全由存储在adr或a-e中的内容决定。如果你不明白他们来自哪里,他们就会看起来像胡言乱语。

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

因此,如果将adr设置为1234567890,则还要设置a到e的值。它们将是任何字节,排列成代表adr的长整数部分。

同样,如果你设置了-e,那么它会损坏" adr的值并更改显示的内容。

答案 2 :(得分:-1)

正确的答案是A.

在第一个printf上,y尚未初始化。因为它是static它是zeo。

在第二个printf y.adr被初始化,但成员没有。因为它们是全球性的,所以它们是零。

在第三个printf上,所有内容都已初始化。 42是ASCII B的十六进制。