有什么好的例子可以说明 astruct和 a之间的区别union吗?基本上我知道它struct使用了其成员的所有内存并union使用了最大的成员内存空间。还有其他操作系统级别的差异吗?
struct
union
使用联合,您应该只使用其中一个元素,因为它们都存储在同一个位置。当您想要存储可能是几种类型之一的东西时,这非常有用。另一方面,结构体的每个元素都有一个单独的内存位置,它们都可以一次使用。
举一个具体的例子来说明它们的使用,不久前我正在研究一个 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。