C语言教程-C语言中的联合体
联合体(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字节,节省了大量的内存空间。