C 语言中的 联合(union
)是一种数据结构,它允许在同一块内存空间中存储不同类型的变量,但一次只能存储其中的一个。联合的特点是多个成员共享同一内存地址,因此,联合类型的大小是其中最大成员的大小。
联合的基本语法
union union_name {
type1 member1;
type2 member2;
type3 member3;
...
};
union_name
:联合类型的名字(可以省略)。type1, type2, ...
:联合成员的类型。member1, member2, ...
:联合成员的名字。
示例
#include <stdio.h>
union Data {
int i;
float f;
char c;
};
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);
data.c = 'A'; // 给字符成员赋值
printf("data.c = %c\n", data.c);
return 0;
}
关键特点:
- 共享内存:
- 联合中的所有成员共享同一块内存,因此它们的内存起始地址是一样的。
- 联合的大小等于最大成员的大小(即所有成员的最大内存需求)。
- 只能存储一个成员的值:
- 在任何时刻,联合只能存储其中的一个成员。给某个成员赋值会覆盖之前存储的值。
联合的大小
联合的大小由其最大成员的大小决定。例如,下面的代码:
union Data {
int i;
float f;
char c;
};
int
通常占用 4 字节。float
通常占用 4 字节。char
占用 1 字节。
因此,联合 Data
的大小将是 4 字节(即最大成员 int
或 float
的大小)。
联合的应用场景
联合常用于以下情况:
- 节省内存:
- 如果你只需要存储一个成员的值,但这个值的类型可能会发生变化(例如,一个数据可以是整数、浮点数或字符),使用联合可以节省内存。
- 多种数据类型的表示:
- 联合可以用来表示一个值的多种类型。例如,在处理不同类型的输入时,可以用联合来存储不同类型的数据。
示例:存储不同类型的数据
假设你需要存储一个数值,它可以是整数、浮点数或字符,可以使用联合来节省内存空间。
#include <stdio.h>
union Value {
int i;
float f;
char c;
};
int main() {
union Value v;
// 存储整数
v.i = 42;
printf("Integer: %d\n", v.i);
// 存储浮点数(覆盖之前存储的整数)
v.f = 3.14;
printf("Float: %.2f\n", v.f);
// 存储字符(覆盖之前存储的浮点数)
v.c = 'A';
printf("Char: %c\n", v.c);
return 0;
}
注意事项
- 成员覆盖:
- 联合中的成员共享同一块内存,这意味着每次赋值都会覆盖之前存储的内容。所以,一次只能存储一个值。
- 内存布局:
- 联合的内存布局与结构体不同。在结构体中,每个成员都有独立的内存空间,而在联合中,所有成员共享同一块内存。
- 联合的访问:
- 访问联合的成员时要小心,因为你只能使用当前有效的成员值。对于其他成员的值,可能会出现未定义的行为。
示例:联合与结构体比较
#include <stdio.h>
// 联合
union Data {
int i;
float f;
char c;
};
// 结构体
struct DataStruct {
int i;
float f;
char c;
};
int main() {
union Data u;
struct DataStruct s;
printf("Size of union: %lu\n", sizeof(u)); // 输出:大小为 4
printf("Size of struct: %lu\n", sizeof(s)); // 输出:大小为 12
return 0;
}
- 你会发现,联合的大小是其最大成员(
int
或float
)的大小,而结构体的大小是所有成员的总和。
总结
- 联合(
union
) 是一种特殊的数据类型,它允许不同类型的成员共享同一块内存。 - 联合的大小由其最大成员的大小决定。
- 联合成员的赋值会覆盖其他成员的值,因此在任意时刻联合只能存储一个值。
- 联合适用于节省内存空间,尤其是当一个变量可能存储不同类型的数据时。
用联合来判断机器的大小端
void check_sys()
{
int a = 1;
int ret = *(char *)&a;
if (ret == 1)
{
printf("小端存储\n");
}
else
printf("大端存储\n");
}
union test
{
int a;
char b;
} u;
void uniontest()
{
u.a = 1;
int ret = u.b;
if (ret == 1)
{
printf("小端存储\n");
}
else
printf("大端存储\n");
}
int main()
{
check_sys();
uniontest();
// union共用一个地址
printf("%p\n%p", &u.a, &u.b);
return 0;
}