定义共用体
共用体是一种特殊的结构体,它允许结构体内多个成员共享同一块内存区域。例如,把一个短整型变量(2个字节)、一个字符型变量和一个双精度浮点变量放在同一个地址开始的内存区域中,内存区域的最大空间为双精度浮点变量占用的字节数。共用体内的短整型变量、字符型变量和双精度浮点变量共同使用该内存区域。这种使几个不同的变量共享同一段内存区域的结构,称为共用体结构。
例如:下面的代码段定义了一个共用体。
union UDATA {
short int age;
double score;
char ch;
};
定义共用体和定义结构体的语法基本相同,定义共用体的C语言关键字为union,该共用体存储结构如下图所示:

从共用体UDATA存储结构图可以看出,age占用2个字节,ch占用1个字节,score占用8个字节。age、ch、score共同占用8个字节的内存区域。
因为共用体的成员共享同一块内存区域,因此共用体变量每次只能使用其中一个成员,一个共用体结构的大小由其最大的成员大小决定。
使用共用体
下面是一个简单的C语言共用体示例。该示例定义了共用体Data,成员包含一个整型变量intVal和一个浮点型变量floatVal。
#include <stdio.h>
// 定义一个共用体
union Data {
int intVal;
float floatVal;
};
int main() {
// 声明一个Data类型的变量data
union Data data;
// 为整型成员赋值
data.intVal = 30;
printf("整型成员的值: %d\n", data.intVal);
// 修改浮点型成员的值,这会覆盖掉整型成员的值
data.floatVal = 3.14f;
printf("浮点型成员的值: %f\n", data.floatVal);
// 尝试访问被覆盖的整型成员,其值已不再是30
printf("被覆盖的整型成员的值: %d\n", data.intVal);
return 0;
}
输出结果:
整型成员的值: 30
浮点型成员的值: 3.140000
// 这个值取决于浮点数3.14在内存中的表示
被覆盖的整型成员的值: 1065353216
上面的示例代码为intVal赋了一个整数值30,然后为floatVal赋了一个浮点数值3.14。因为intVal和floatVal共享同一块内存,所以当floatVal被赋值后,intVal的值就被覆盖了。当我们尝试访问被覆盖的intVal时,得到的是一个与原始值不同的结果,这个结果是浮点数3.14在内存中的表示,转换为整型后的值。
结构体内嵌共用体
在C语言中,可以将共用体嵌套到结构体中。这种嵌套结构允许在一个结构体中组合多种数据类型,并且可以有效利用内存,因为共用体成员会共享同一块内存空间。
下面是一段C语言代码示例,展示了如何将共用体嵌套到结构体中:
#include <stdio.h>
#include <string.h>
// 定义一个共用体,包含整型和浮点型成员
union Number {
int intValue;
float floatValue;
};
// 定义一个结构体,包含一个字符串和一个嵌套的共用体成员
struct Person {
char name[50];
union Number number;
};
int main() {
struct Person person;
// 设置结构体成员
strcpy(person.name, "Alice");
person.number.intValue = 30;
// 输出结构体成员的值
printf("Name: %s\n", person.name);
printf("Integer value: %d\n", person.number.intValue);
// 将共用体整型成员的值修改为浮点型值
person.number.floatValue = 3.14f;
// 输出结构体浮点成员的值
printf("Float value: %f\n", person.number.floatValue);
return 0;
}
上面的示例代码定义了一个名为Number的共用体,包含了一个整型成员intValue和一个浮点型成员floatValue。然后定义了一个Person结构体,它包含了一个字符串成员name和一个Number类型的共用体成员number。
在main函数中,创建了一个Person类型的变量person,并设置name和number.intValue成员,并输出这些值。然后将number.intValue的值修改为number.floatValue的值并输出。
使用指针操作共用体
下面的示例代码,展示了如何使用指针来操作共用体中的数据:
上面的示例代码,定义了一个名为Data的共用体,它包含了一个整型成员intVal和一个浮点型成员floatVal。然后声明了一个指向Data类型的指针pData,并将它指向data变量。
8.3.5.共用体数组
共用体也可以作为数组结构的元素,由共用体构成的数组结构可以存储不同类型的数据。需要注意的是,由于共用体成员共享内存空间,数组中每个元素的不同成员不会保存各自独立的数据。
#include <stdio.h>
// 定义一个共用体
union Data {
int intVal;
float floatVal;
};
int main() {
// 声明一个Data类型的变量data
union Data data;
// 声明一个指向Data类型的指针,并指向data
union Data *pData = &data;
// 使用指针访问和修改整型成员
pData->intVal = 42;
printf("整型成员的值: %d\n", pData->intVal);
// 使用指针访问和修改浮点型成员
pData->floatVal = 3.14f;
printf("浮点型成员的值: %f\n", pData->floatVal);
// 由于共用体成员共享内存,修改一个成员会影响另一个成员
printf("整型成员(被浮点型成员覆盖后)的值: %d\n", pData->intVal);
return 0;
}
下面的示例代码,展示了如何声明和使用共用体数组:
#include <stdio.h>
// 定义一个共用体
union Data {
int intValue;
float floatValue;
char charValue;
};
int main() {
// 声明一个包含3个元素的共用体数组
union Data array[3];
// 使用数组的第一个元素
array[0].intValue = 10;
printf("第一个元素的整数值: %d\n", array[0].intValue);
// 修改数组第一个元素的浮点值,这会覆盖掉之前的整数值
array[0].floatValue = 20.5f;
printf("第一个元素的浮点值: %f\n", array[0].floatValue);
// 尝试访问被覆盖的整数值,它现在包含了浮点数的二进制表示
printf("第一个元素被覆盖后的整数值: %d\n", array[0].intValue);
// 使用数组的第二个和第三个元素
array[1].charValue = 'A';
printf("第二个元素的字符值: %c\n", array[1].charValue);
array[2].floatValue = 30.75f;
printf("第三个元素的浮点值: %f\n", array[2].floatValue);
return 0;
}
上面的示例代码定义了一个名为Data的共用体,在main函数内部声明了array数组,数组元素类型为Data。
由于共用体成员共享内存,数组中每个元素的不同成员不会保存各自独立的数据。例如,当为array[0]设置了浮点值后,它的整数值就被覆盖了。同样array[1]的字符值会覆盖其整型和浮点型成员的值。
共用体数组在某些特定场景下非常有用。例如当你需要在一个数组中存储不同类型的数据,并且这些数据不会同时被使用时,就可以使用共用体数组。