联合体(Union)可以被定义为用户自定义的数据类型,它是由不同数据类型的不同变量组成的,但这些变量在同一内存位置上。联合体也可以被定义为具有多个成员,但在特定时刻只能有一个成员包含值。

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

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

struct abc 
{ 
  int a; 
  char b;  
};

上述代码是一个用户自定义的结构体,它包含两个成员,即类型为int的'a'和类型为字符的'b'。当我们检查'a'和'b'的地址时,发现它们的地址是不同的。因此,我们得出结论结构体的成员不共享同一内存位置。

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

让我们来看看内存分配的图示表示。

结构体有两个成员,一个是整数类型,另一个是字符类型。由于1个块等于1字节,因此变量'a'将分配4个块的内存,而变量'b'将分配1个块的内存。这两个变量共享同一内存位置,并具有相同的初始地址。

在联合体中,成员将共享内存位置。如果我们尝试更改任何一个成员的值,另一个成员的值也会随之改变。让我们通过一个示例来理解这个概念。

union abc 
{ 
  int a; 
  char b;  
} var; 

int main() 
{ 
  var.a = 66; 
  printf("\na = %d", var.a); 
  printf("\nb = %d", var.b); 
}

上述代码中,联合体有两个成员,即'a'和'b'。'var'是联合体abc类型的变量。在main()函数中,我们将66赋给'a'变量,所以var.a将在屏幕上打印出66。由于'a'和'b'共享内存位置,var.b将打印出'B'(66的ASCII码)。

确定联合体的大小

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

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

union abc{ 
  int a; 
  char b; 
  float c; 
  double d; 
}; 

int main()
{ 
  printf("Size of union abc is %d", sizeof(union abc)); 
  return 0; 
}

我们知道,整数的大小为4字节,字符的大小为1字节,浮点数的大小为4字节,双精度数的大小为8字节。由于双精度变量占用的内存最多,所以总共分配8字节的内存。因此,上述程序的输出结果为8字节。

使用指针访问联合体的成员

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

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

#include <stdio.h> 

union abc 
{ 
  int a; 
  char b; 
}; 

int main() 
{ 
  union abc *ptr; // 指针变量声明
  union abc var; 
  var.a = 90; 
  ptr = &var; 
  printf("The value of a is : %d", ptr->a); 
  return 0; 
}

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

为什么需要C语言的联合体?

考虑以下一个例子来理解为什么需要C语言的联合体。假设有一个商店,里面有两种物品:

  • 书籍
  • 衬衫

店主希望存储上述两种物品的记录以及相关信息。例如,书籍包括标题、作者、页数、价格,衬衫包括颜色、设计、尺寸和价格。'价格'属性在两种物品中是公共的。店主想要存储这些属性,那么他/她将如何存储这些记录。

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

struct store 
{ 
  double price; 
  char *title; 
  char *author; 
  int number_pages; 
  int color; 
  int size; 
  char *design; 
};

上述结构体包含了店主希望存储的所有物品。上述结构体完全可用,但是'price'是两种物品中的共同属性,而其余的属性是各自独立的。像价格、title、author和number_pages这样的属性属于书籍,而color、size和*design则属于衬衫。

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

int main() 
{ 
  struct store book; 
  book.title = "C programming"; 
  book.author = "Paulo Cohelo";  
  book.number_pages = 190; 
  book.price = 205; 
  printf("Size is : %ld bytes", sizeof(book)); 
  return 0; 
}

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

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

struct store 
{ 
  double price; 
  union 
  { 
    struct 
    { 
      char *title; 
      char *author; 
      int number_pages; 
    } book; 
    
    struct 
    { 
      int color; 
      int size; 
      char *design; 
    } shirt; 
  } item; 
}; 

int main() 
{ 
  struct store s; 
  s.item.book.title = "C programming";  
  s.item.book.author = "John"; 
  s.item.book.number_pages = 189; 
  printf("Size is %ld", sizeof(s)); 
  return 0; 
}

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

标签: c语言, c语言教程, c语言技术, c语言学习, c语言学习教程, c语言下载, c语言开发, c语言入门教程, c语言进阶教程, c语言高级教程, c语言面试题, c语言笔试题, c语言编程思想