【问题标题】:Describe what's happening with this union描述这个工会发生了什么
【发布时间】:2015-11-05 18:44:40
【问题描述】:

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

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

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 是正确的答案。不幸的是,我也不确定这里会发生什么。有人能给我们详细介绍一下这段代码的作用并帮助我们理解答案吗?提前致谢!

【问题讨论】:

  • 所以“你的朋友”应该问问自己。
  • 这会调用未定义的行为。
  • 为什么your friend 期望答案是C
  • 以上都不是。 ? 值不是随机的。它们取决于机器的字节序,以及long 中的字节数。如果格式说明符中没有拼写错误,您会更好。
  • 我明白了,但这个问题非常具有误导性。如果y 声明为静态范围,那么它零初始化的。

标签: c struct unions


【解决方案1】:

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

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

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

因此,如果您将 adr 设置为 1234567890,那么您也在设置 a 到 e 的值。它们将是发生在表示 adr 的 long 部分的任何字节。

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

【讨论】:

  • 它们没有明确定义,因为没有关于对齐、填充或每种类型大小的信息。
  • 同意。为了简短的回答,我选择将其排除在外。定义不明确,但确定性。我只是不同意“随机”数字作为描述。我认为这意味着未初始化(仍然不是随机的,但更接近它)。
  • 对不起,这实际上是我对练习的糟糕翻译(不是用英文写的)。我知道这不是随机的,但是是的,我说的是未初始化的值。
  • 嗯,就是这样,@maxdefolsch。它们在那时被初始化,因为它是我们正在讨论的联合。它们相等的是依赖于架构,但它们不是未初始化的。
  • 在数字计算机上很难做到真正的不确定性。但是,它是未指定的,并且 很重要。对 DV 很感兴趣,但你的答案太正确了。
【解决方案2】:

答案可能是选择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 位机器。

【讨论】:

  • 我认为显示字节是什么以及如何转换为十六进制会产生误导。在某些架构中,long 可能是 8 个字节,然后根据 endieness 和打包 a-d 可能是 0,甚至!也许最好设置一个具有已定义架构等的示例,以展示该示例可能是什么?
  • 不能不同意你的观点,但我的回答是基于一些众所周知的假设和答案中给出的选项。
【解决方案3】:

正确答案是A。

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

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

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

【讨论】:

  • 不正确。这里有一个 union,所以 adr 和 struct x 的值在内存中是重叠的。改变一个改变另一个。
  • 工会不是这样运作的。如果你在 y.adr 中设置了一个值,你也同时“设置”了值 a-e,因为它们在同一个内存区域中。
  • 愚蠢的我......没看到工会。我的考试不及格:-)
猜你喜欢
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多