文章目录
- 一、前言
- 二、联合体的定义与使用
-
- [1. 联合体的定义](#1. 联合体的定义)
- [2. 联合体与结构体的区别](#2. 联合体与结构体的区别)
- 三、联合体的使用场景
-
- [1. 节省内存](#1. 节省内存)
- [2. 位域与联合体](#2. 位域与联合体)
- 四、联合体的限制与注意事项
- 五、总结
一、前言
在C语言中,联合体(union) ,又称为共用体 ,是一种特殊的数据结构。它与结构体类似,但所有成员共享同一块内存,因此可以在不同时间存储不同类型的数据。联合体在节省内存和处理多态数据时非常有用。
二、联合体的定义与使用
1. 联合体的定义
在C语言中,使用 union
关键字定义联合体,其语法格式如下:
c
union 联合体名 {
数据类型 成员1;
数据类型 成员2;
...
};
✅ 示例:
c
#include <stdio.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 = %.2f\n", data.f);
sprintf(data.str, "Hello, C!");
printf("data.str = %s\n", data.str);
// 查看内存大小
printf("sizeof(data) = %lu 字节\n", sizeof(data));
return 0;
}
✅ 运行结果:
data.i = 10
data.f = 220.50
data.str = Hello, C!
sizeof(data) = 20 字节
说明:
data.i
、data.f
和data.str
共享同一块内存。- 修改其中一个成员后,其他成员的值可能会被覆盖。
sizeof(data)
显示的是联合体中占用最大内存的成员的大小,而不是所有成员大小的总和。
2. 联合体与结构体的区别
特性 | 联合体 union |
结构体 struct |
---|---|---|
内存分配 | 所有成员共享同一块内存 | 每个成员独立占据内存 |
占用内存大小 | 取最大成员的内存大小 | 所有成员大小的总和 |
数据存储 | 同一时刻只能存储一个成员的数据 | 可同时存储所有成员的数据 |
数据访问 | 修改一个成员,其他成员可能被覆盖 | 修改一个成员不会影响其他成员 |
✅ 示例对比:
c
#include <stdio.h>
#include <string.h>
struct StructExample {
int i;
float f;
char str[20];
};
union UnionExample {
int i;
float f;
char str[20];
};
int main() {
struct StructExample s = {10, 220.5, "Struct"};
union UnionExample u;
u.i = 10;
printf("Union i: %d\n", u.i);
u.f = 220.5; // 修改 f 会覆盖 i 的值
printf("Union f: %.2f\n", u.f);
strcpy(u.str, "Union");
printf("Union str: %s\n", u.str);
// 查看内存占用
printf("sizeof(struct) = %lu 字节\n", sizeof(s));
printf("sizeof(union) = %lu 字节\n", sizeof(u));
return 0;
}
✅ 运行结果:
Union i: 10
Union f: 220.50
Union str: Union
sizeof(struct) = 28 字节
sizeof(union) = 20 字节
三、联合体的使用场景
1. 节省内存
在内存紧张 的情况下,联合体可以用于存储多种数据类型,但只在不同时间使用其中一种。例如:
- 存储网络包的数据时,不同类型的数据包可能占用不同的数据结构。
- 解析二进制数据时,以多种格式读取同一块内存。
✅ 示例:
c
#include <stdio.h>
union Packet {
int id;
float value;
char msg[16];
};
int main() {
union Packet pkt;
pkt.id = 1234;
printf("ID: %d\n", pkt.id);
pkt.value = 56.78; // 修改浮点数,覆盖 id
printf("Value: %.2f\n", pkt.value);
sprintf(pkt.msg, "Hello, World!");
printf("Msg: %s\n", pkt.msg);
return 0;
}
2. 位域与联合体
联合体常与位域 结合使用,以实现位操作和数据解析。
✅ 示例:解析IP地址
c
#include <stdio.h>
#include <stdint.h>
union IPAddress {
uint32_t ip;
struct {
uint8_t byte1;
uint8_t byte2;
uint8_t byte3;
uint8_t byte4;
} bytes;
};
int main() {
union IPAddress addr;
addr.ip = 0xC0A80101; // 192.168.1.1
printf("IP地址: %d.%d.%d.%d\n",
addr.bytes.byte1,
addr.bytes.byte2,
addr.bytes.byte3,
addr.bytes.byte4);
return 0;
}
✅ 运行结果:
IP地址: 192.168.1.1
解析说明:
- 使用联合体将 IP 地址表示为整数 或字节数组。
- 便于在不同格式之间切换。
四、联合体的限制与注意事项
- 只能同时存储一个成员的数据
- 修改一个成员时,其他成员的数据会被覆盖。
- 内存对齐问题
- 联合体在内存中可能存在对齐填充 ,需使用
#pragma pack
控制。
- 联合体在内存中可能存在对齐填充 ,需使用
- 适用于特定场景
- 联合体适合节省内存、处理多态数据,不适合存储多个成员的数据。
- 无法初始化多个成员
- C语言中,联合体在声明时只能初始化第一个成员。
✅ 示例:
c
union Example {
int x;
float y;
};
int main() {
union Example e = {100}; // 初始化第一个成员
// e = {100, 3.14}; // ❌错误:不能初始化多个成员
return 0;
}
五、总结
- 联合体是一种内存共享的数据结构,适合在不同时刻存储不同类型的数据。
- 与结构体不同,联合体的内存大小由最大成员决定。
- 联合体常用于节省内存、处理多态数据、解析二进制数据等场景。
- 使用联合体时需要注意数据覆盖问题,避免误用导致数据丢失。