我认为你对于联合体有一些误解。
使用联合体的想法是为了节省内存...
是的,这是一个原因。
... 并且获得与结构体等效的结果...
不是的。
它们在源代码中看起来很相似,但实际上却完全不同,就像苹果和飞机一样。联合体是一种非常低级别的结构,可以让您将一段内存视为存储其任何"成员",但您每次只能使用一个。即使使用单词"成员"本身就非常误导人, 它们应该被称为"视图"或其他名称,而不是成员。
当你写下:
union ABCunion
{
int a;
double b;
char c;
} myAbc;
你说:"取一个足够大以容纳int、char和double中最大的一个的内存块,然后称其为
myAbc。"
在这个内存块里,你现在可以存储
一个int、
一个double或
一个char。如果你存储了一个int,然后再存储一个double,那么int就永远消失了。
那这样做有什么意义呢?
联合体有两个主要用途。
a) 区分式存储
这就是我们上面所做的。我选择一块内存并根据上下文给它赋予不同的含义。有时上下文是明确的(你保留了一些变量来指示你存储的“变量”种类),有时它可以是隐含的(基于代码段,你可以知道哪个变量必须在使用中)。无论哪种方式,代码都需要能够弄清楚,否则你将无法对变量进行任何明智的操作。
一个典型(显式)的例子是:
struct MyVariantType
{
int typeIndicator ; // type=1 -> It's an int,
// type=2 -> It's a double,
// type=3 -> It's a char
ABCunion body;
};
例如,VB6的“变量”是类似于上面所述(但更复杂)的联合体。
b) 拆分表示
当您需要将变量视为“整体”或部分组合时,此方法有时非常有用。以下示例更易于理解:
union DOUBLEBYTE
{
struct
{
unsigned char a;
unsigned char b;
} bytes;
short Integer;
} myVar;
这里有一个短整型的联合体和一对字节。现在,您可以将相同的值视为短整型 (myVar.Integer),也可以轻松地分析构成该值的单个字节 (myVar.bytes.a 和 myVar.bytes.b)。
请注意,第二种用法不可移植(我非常确定);这意味着它不能保证在不同的计算机架构上工作;但是这种用法对于 C 设计的任务(操作系统实现)绝对必要。
int
类型变量a
的起始地址将在c
变量结束后的 3 字节处,编译器会添加填充以确保对a
的访问正确对齐。 - Jonathan Leffler