小编典典

结构和联合之间的区别

all

有什么好的例子可以说明 astruct
a之间的区别union吗?基本上我知道它struct使用了其成员的所有内存并union使用了最大的成员内存空间。还有其他操作系统级别的差异吗?


阅读 102

收藏
2022-03-17

共1个答案

小编典典

使用联合,您应该只使用其中一个元素,因为它们都存储在同一个位置。当您想要存储可能是几种类型之一的东西时,这非常有用。另一方面,结构体的每个元素都有一个单独的内存位置,它们都可以一次使用。

举一个具体的例子来说明它们的使用,不久前我正在研究一个 Scheme 解释器,我基本上是将 Scheme 数据类型覆盖到 C
数据类型上。这涉及在结构中存储一个指示值类型的枚举和一个存储该值的联合。

union foo {
  int a;   // can't use both a and b at once
  char b;
} foo;

struct bar {
  int a;   // can use both a and b simultaneously
  char b;
} bar;

union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!

struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK

编辑: 如果您想知道将 xb 设置为 ‘c’ 会将 xa 的值更改为什么,从技术上讲,它是未定义的。在大多数现代机器上,一个 char 是 1
个字节,一个 int 是 4 个字节,所以给 xb 值 ‘c’ 也会给 xa 的第一个字节同样的值:

union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);

印刷

99, 99

为什么这两个值相同?因为 int 3 的最后 3 个字节全为零,所以它也读作 99。如果我们为 xa 输入一个更大的数字,你会发现情况并非总是如此:

union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);

印刷

387427, 99

为了仔细查看实际的内存值,让我们设置并打印出十六进制的值:

union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);

印刷

deadbe22, 22

您可以清楚地看到 0x22 覆盖 0xEF 的位置。

在 C 中,未定义 int 中的字节顺序。这个程序在我的 Mac 上用 0x22 覆盖了 0xEF,但是在其他平台上它会覆盖 0xDE,因为构成
int 的字节顺序被颠倒了。因此,在编写程序时,永远不要依赖覆盖联合中特定数据的行为,因为它不可移植。

有关字节顺序的更多信息,请查看endianness

2022-03-17