C 语言中的联合(Union)

2025年3月28日 | 阅读 5 分钟

联合(Union)可以定义为一种用户定义的数据类型,它是在同一内存位置中不同数据类型的不同变量的集合。联合也可以定义多个成员,但在特定时间点,只有一个成员可以包含值。

联合是一种用户定义的数据类型,但与结构体不同,它们共享相同的内存位置。

让我们通过一个例子来理解这一点。

上面的代码是用户定义的结构体,它由两个成员组成,即 **int** 类型的 'a' 和 **char** 类型的 'b'。当我们检查 'a' 和 'b' 的地址时,我们发现它们的地址是不同的。因此,我们得出结论,结构体中的成员不共享相同的内存位置。

当我们定义联合时,我们发现联合的定义方式与结构体相同,但区别在于联合数据类型使用 **union** 关键字定义,而结构体使用 **struct** 关键字定义。联合包含数据成员,即 'a' 和 'b',当我们检查这两个变量的地址时,我们发现它们都具有相同的地址。这意味着联合成员共享相同的内存位置。

让我们看一下内存分配的图示。

下图显示了结构体的图示。结构体有两个成员;即,一个是整数类型,另一个是字符类型。由于 1 块等于 1 字节;因此,变量 'a' 将分配 4 个内存块,而变量 'b' 将分配 1 个内存块。

下图显示了联合成员的图示。两个变量共享相同的内存位置并具有相同的初始地址。

在联合中,成员将共享内存位置。如果我们尝试更改任何成员,它也会反映到另一个成员。让我们通过一个例子来理解这个概念。

在上面的代码中,联合有两个成员,即 'a' 和 'b'。'var' 是联合 abc 类型的一个变量。在 **main()** 方法中,我们将 66 赋值给变量 'a',因此 var.a 将在屏幕上打印 66。由于 'a' 和 'b' 共享内存位置,**var.b** 将打印 'B'(66 的 ASCII 码)。

决定联合的大小

联合的大小基于联合中最大成员的大小。

让我们通过一个例子来理解。

众所周知,int 的大小是 4 字节,char 的大小是 1 字节,float 的大小是 4 字节,double 的大小是 8 字节。由于 double 变量在所有四个变量中占用最大的内存,因此总共会分配 8 字节的内存。因此,上述程序的输出将是 8 字节。

使用指针访问联合成员

我们可以通过使用 (->) 箭头运算符通过指针访问联合的成员。

让我们通过一个例子来理解。

示例

编译并运行

在上面的代码中,我们创建了一个指针变量,即 *ptr,它存储了 var 变量的地址。现在,ptr 可以通过使用 (->) 运算符访问变量 'a'。因此,上述代码的输出将是 90。

为什么我们需要 C 联合?

考虑一个例子来理解 C 联合的必要性。让我们考虑一家商店有两件商品:

  • 书籍
  • 衬衫

店主想要存储上述两件商品的记录以及相关信息。例如,图书包括标题、作者、页数、价格,而衬衫包括颜色、设计、尺寸和价格。‘价格’属性在这两件商品中是通用的。店主想要存储这些属性,那么他/她将如何存储这些记录呢?

最初,他们决定将记录存储在如下所示的结构体中:

上述结构体包含店主想要存储的所有商品。上述结构体完全可用,但价格是两件商品的共同属性,而其余商品是单独的。价格、*标题、*作者和页数等属性属于图书,而颜色、尺寸、*设计属于衬衫。

让我们看看如何访问结构体的成员.

在上面的代码中,我们创建了一个 **store** 类型的变量。我们给变量 title、author、number_pages、price 赋值,但 book 变量不具有 size、color 和 design 等属性。因此,这是一种内存浪费。上述结构体的大小将是 44 字节。

如果我们使用联合,我们可以节省大量空间。

示例

编译并运行

在上面的代码中,我们创建了一个 store 类型的变量。由于我们在上面的代码中使用了联合,所以将考虑变量占用的最大内存进行内存分配。上述程序的输出是 32 字节。在结构体的情况下,我们获得了 44 字节,而在联合的情况下,获得的大小是 32 字节。因此,44 字节大于 32 字节,节省了大量的内存空间。