C 联合体类型简介
在 C 语言中,联合体也是一种用户自定义的数据类型(与结构体类似)。它可以包含多个不同类型的成员。
语法:
union 类型名
{
类型1 成员名1;
类型2 成员名2;
……
类型n 成员名n;
};说明:
union 是定义联合体的关键字。“类型名” 是联合体的名称,该名字是可以省略的。然后大括号 “{}” 中声明了联合体的成员,每个成员都有自己的类型和名称。
联合体的所有成员共享同一块内存空间,该内存空间的大小由联合体中占用内存最多的成员决定。与结构体类似,定义联合体类型时,大括号后面的分号不能省略。
使用联合体的主要目的是节省内存。当需要存储多种不同类型的数据,但同一时间只需要使用其中一种时,联合体可以有效地利用内存。
注意: 结构体中每个成员都拥有独立的内存空间,而联合体的所有成员共享同一块内存空间。这意味着在任何给定的时间,联合体中只有一个成员是活动的。
示例 1:联合体的基本用法
#include <stdio.h>
#include <string.h>
// 定义一个联合体类型
union Data
{
int i;
float f;
char str[20];
};
int main(void)
{
// 定义一个联合体变量
union Data data;
// 存储整数
data.i = 666;
printf("%d\n",data.i);
// 存储浮点数 (会覆盖之前的整数值)
data.f = 3.14;
printf("%f\n", data.f);
// 存储字符串 (会覆盖之前的浮点数值)
strcpy(data.str, "lvyenet");
printf("%s\n", data.str);
return 0;
}运行结果如下。
666
3.140000
lvyenet分析:
在上面例子中,我们使用 union 关键字定义了一个名为 Data 的联合体类型。Data 联合体包含 3 个成员:一个 int 类型的 i,一个 float 类型的 f,以及一个 char 数组 str。
在 main 函数 中,定义了一个 Data 类型的联合体变量 data。我们先将整数 666 赋值给 data.i 并打印出来,然后将浮点数 3.14 赋值给 data.f。此时,之前存储在同一内存位置的整数值就被覆盖了。最后,我们使用 strcpy() 函数将字符串 "lvyenet" 复制到 data.str 中。同样地,之前存储的浮点数值也被覆盖了。
从这个例子,我们可以非常直观地理解了联合体的特性,也就是:所有成员共享同一块内存空间,在任何时候只有一个成员的值是有效的。
C 定义联合体变量
在 C 语言中,定义联合体变量的方式与定义结构体变量类似,主要有以下 3 种方式。
1. 先定义类型,后定义变量
union Data
{
int i;
float f;
char str[20];
};
union Data data;2. 定义类型的同时定义变量(带类型名)
union Data
{
int i;
float f;
char str[20];
} data;3. 定义类型的同时定义变量(不带类型名)
union
{
int i;
float f;
char str[20];
} data;与结构体类似,第 3 种方式在实际开发中很少会使用。
C 访问联合体变量
在 C 语言中,访问联合体成员的方式与访问结构体成员完全相同,都是使用点运算符 (.)。
语法:
联合体变量名.成员名示例 2:访问联合体成员
#include <stdio.h>
#include <string.h>
union Student
{
char name[20];
int age;
float score;
};
int main(void)
{
union Student stu;
strcpy(stu.name, "阿莫");
printf("name: %s\n", stu.name);
stu.age = 20;
printf("age: %d\n", stu.age);
return 0;
}运行结果如下。
name: 阿莫
age: 20分析:
上面例子定义了一个 Student 联合体,它可以存储学生的姓名(字符串)、年龄(整数)或分数(浮点数)。我们首先存储了学生的姓名,并将其打印出来。然后,我们存储了年龄,并再次打印出来。需要注意的是,当我们存储年龄时,之前存储的姓名已经被覆盖了。
C 联合体的大小
在 C 语言中,联合体的大小是其最大的成员所占用的内存大小。这是因为联合体的所有成员共享同一块内存空间,这块空间必须足够容纳最大的成员。
示例 3:获取联合体的大小
#include <stdio.h>
union Data
{
int a;
double b;
char c[20];
};
int main(void)
{
union Data data;
printf("联合体大小: %lu bytes\n", sizeof(data));
return 0;
}运行结果如下。(不同系统的结果可能不一样)
联合体大小: 24 bytes分析:
在这个例子中,Data 联合体包含一个 int ( 通常 4 字节 ), 一个 double ( 通常 8 字节 ), 和一个 char 数组 (20 字节 )。由于 char 数组 c 占用 20 个字节,是联合体最大的成员。
这里小伙伴们就会问了:“为什么打印结果不是 20,而是 24 呢?”。这是因为联合体的大小通常需要对齐到最大成员的对齐要求。在大多数系统中,double 的对齐要求是 8 字节,因此联合体的大小会被对齐到 24 字节(因为 20 不是 8 的倍数,需要补齐到 24)。
C 联合体的应用场景
在实际开发中,C 联合体在以下情况下非常有用:
- 节省内存:当需要在同一内存位置存储不同类型的数据,但同一时间只需要使用其中一种时,可以使用联合体来节省内存空间。
- 类型转换:联合体可以用于进行低级别的类型转换,尽管这种做法需要谨慎,因为它可能导致不可移植的行为。
- 数据表示:当需要以多种不同的方式解释同一块内存数据时,可以使用联合体。例如,一个 32 位的整数可以被解释为四个 8 位的字符。
C 联合体与结构体的区别
在 C 语言中,联合体和结构体都是用户自定义的数据类型,它们都可以包含多个不同类型的成员。但它们之间存在着本质的区别:
- 内存分配:结构体的每个成员都拥有独立的内存空间,结构体变量的总大小是其所有成员大小之和(可能存在内存对齐)。而联合体的所有成员共享同一块内存空间,联合体变量的大小等于其最大的成员的大小。
- 数据存储:在任何给定的时间,结构体变量可以存储其所有成员的值。而联合体变量在任何给定的时间只能存储其一个成员的值。如果给联合体的一个成员赋值,其他成员的值将会被覆盖。
