1、定义声明
共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。共用体有时也被称为联合或者联合体。其定义格式为:
union 共用体名{
成员列表
};
例如,
union Data { int i; float f; char str[20]; };
1)共用体也是一种自定义类型,可以通过它来创建变量
例如,
union data{ int n; char ch; double f; }; union data a, b, c;
2)定义共用体的同时创建变量
union data{ int n; char ch; double f; } a, b, c;
3)如果不再定义新的变量,也可以将共用体的名字省略
union{ int n; char ch; double f; } a, b, c;
例如,
#include <stdio.h> union data{ int n; char ch; short m; }; int main(){ union data a; printf("%d, %d\n", sizeof(a), sizeof(union data) ); a.n = 0x40; printf("%X, %c, %hX\n", a.n, a.ch, a.m); a.ch = '9'; printf("%X, %c, %hX\n", a.n, a.ch, a.m); a.m = 0x2059; printf("%X, %c, %hX\n", a.n, a.ch, a.m); a.n = 0x3E25AD54; printf("%X, %c, %hX\n", a.n, a.ch, a.m); return 0; }
2、访问共用体成员
访问共用体的成员,需要使用成员访问运算符(.
)。
例如,
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; data.i = 10; data.f = 220.5; strcpy( data.str, "C 语言"); printf( "data.i : %d\n", data.i); printf( "data.f : %f\n", data.f); printf( "data.str : %s\n", data.str); return 0; }
上面示例的输出结果中,共用体的 i 和 f 成员的值有损坏,因为最后赋给变量的值占用了内存位置,这也是 str 成员能够完好输出的原因。
共用体是任何时候只能有一个成员带有值。同一时间应该只用一个成员。
例如,
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; data.i = 10; printf( "data.i : %d\n", data.i); data.f = 220.5; printf( "data.f : %f\n", data.f); strcpy( data.str, "C 语言"); printf( "data.str : %s\n", data.str); return 0; }
3、共用体的内存分配
共用体的所有成员共享同一块内存,共用体的大小是它所有成员中最大成员的大小。
#include <stdio.h> union Data { int i; float f; char c; }; int main() { printf("Size of union Data: %lu bytes\n", sizeof(union Data)); return 0; }
4、共用体的使用场景
当一个变量在不同时间需要存储不同类型的数据时,共用体可以节省内存。
在嵌入式编程中,共用体常用于将一段二进制数据解释为不同的数据类型。
在硬件寄存器编程中,可以通过共用体以不同的格式访问同一寄存器。
1)节省内存的共用体
存储一个学生的标识,可能是学生的学号(整数)、图书馆卡号(字符串)或成绩(浮点数),但在任何时间只有其中一种。
#include <stdio.h> // 定义一个共用体 union StudentInfo { int id; float grade; char libraryCard[20]; }; int main() { union StudentInfo student; student.id = 12345; printf("Student ID: %d\n", student.id); student.grade = 87.5; printf("Student Grade: %.2f\n", student.grade); // 复制字符串到共用体的字符数组中 snprintf(student.libraryCard, sizeof(student.libraryCard), "LIB2023ABC"); printf("Library Card: %s\n", student.libraryCard); return 0; }
2)共用体在硬件寄存器编程中的应用
在嵌入式系统中,往往需要直接访问硬件寄存器中的特定位,可以使用共用体来达到这一目的。
#include <stdio.h> // 定义一个共用体,用于访问32位寄存器的不同位段 union Register { unsigned int reg; struct { unsigned int lowByte : 8; // 低8位 unsigned int midByte : 8; // 中间8位 unsigned int highByte : 8; // 高8位 unsigned int control : 8; // 控制位 }; }; int main() { union Register reg; // 直接访问整个寄存器 reg.reg = 0x12345678; printf("Register value: 0x%X\n", reg.reg); printf("Low Byte: 0x%X\n", reg.lowByte); printf("Mid Byte: 0x%X\n", reg.midByte); printf("High Byte: 0x%X\n", reg.highByte); printf("Control: 0x%X\n", reg.control); return 0; }
注意:
由于共用体的所有成员共享同一段内存,赋值一个成员会覆盖其他成员的值。
如果在共用体中同时访问多个成员,结果是未定义的,因为你无法预期其他成员会有什么值。
在一些内存受限的场合,如嵌入式系统,共用体可以显著减少内存使用量。