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;
}
注意:
由于共用体的所有成员共享同一段内存,赋值一个成员会覆盖其他成员的值。
如果在共用体中同时访问多个成员,结果是未定义的,因为你无法预期其他成员会有什么值。
在一些内存受限的场合,如嵌入式系统,共用体可以显著减少内存使用量。