1、定义声明
共用体是一种特殊的数据类型,可以在相同的内存位置存储不同的数据类型。可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。共用体有时也被称为联合或者联合体。其定义格式为:
union 共用体名{
成员列表
};
例如,
#include <iostream>
#include <cstring> // 用于字符串操作
using namespace std;
union Data {
int i;
float f;
char str[20];
};
int main() {
Data data;
// 使用整数成员
data.i = 42;
cout << "Integer: " << data.i << endl;
// 使用浮点成员,覆盖之前的整数值
data.f = 3.14;
cout << "Float: " << data.f << endl;
// 使用字符串成员,覆盖之前的浮点值
strcpy(data.str, "Hello, Union");
cout << "String: " << data.str << endl;
// 再次尝试访问覆盖的整数和浮点成员(未定义行为)
cout << "Overwritten Integer: " << data.i << endl;
cout << "Overwritten Float: " << data.f << endl;
return 0;
}
1)共用体也是一种自定义类型,可以通过它来创建变量
例如,
#include <stdio.h>
using namespace std;
union data {
int n;
char ch;
double f;
};
int main() {
// 定义 union 变量
union data a, b, c;
// 为 union 成员赋值
a.n = 42; // 将整数赋值给 a.n
b.ch = 'A'; // 将字符赋值给 b.ch
c.f = 3.14; // 将浮点数赋值给 c.f
// 输出 union 成员的值
printf("a.n: %d\n", a.n); // 访问整数值
printf("b.ch: %c\n", b.ch); // 访问字符值
printf("c.f: %.2f\n", c.f); // 访问浮点数值
// 注意:访问一个 union 的成员时,其他成员的数据可能会被覆盖
a.f = 1.23; // 重新为 a.f 赋值
printf("a.f: %.2f\n", a.f); // 此时只能正确访问 a.f
return 0;
}
2)定义共用体的同时创建变量
#include <iostream>
using namespace std;
union Data {
int n;
char ch;
double f;
} a, b, c;
int main() {
// 使用共用体变量
a.n = 42;
b.ch = 'A';
c.f = 3.14;
// 输出值
cout << "a.n = " << a.n << endl;
cout << "b.ch = " << b.ch << endl;
cout << "c.f = " << c.f << endl;
return 0;
}
3)如果不再定义新的变量,也可以将共用体的名字省略
#include <iostream>
using namespace std;
union {
int n;
char ch;
double f;
} a, b, c;
int main() {
// 使用匿名共用体的变量
a.n = 42;
b.ch = 'B';
c.f = 3.14;
// 输出值
cout << "a.n = " << a.n << endl; // 输出变量 a 的整数值
cout << "b.ch = " << b.ch << endl; // 输出变量 b 的字符值
cout << "c.f = " << c.f << endl; // 输出变量 c 的浮点值
return 0;
}
2、访问共用体成员
访问共用体的成员,需要使用成员访问运算符(.
)。
例如,
#include <iostream>
using namespace std;
#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/C++ 语言");
cout << "data.i : " << data.i << endl;
cout << "data.f : " << data.f << endl;
cout << "data.str : " << data.str << endl;
return 0;
}
注意:上面示例的输出结果中,共用体的 i
和 f
成员的值有损坏,因为最后赋给变量的值占用了内存位置,这也是 str 成员能够完好输出的原因。
共用体是任何时候只能有一个成员带有值。同一时间应该只用一个成员。
例如,
#include <iostream>
using namespace std;
#include <string.h>
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
data.i = 10;
cout << "data.i : " << data.i << endl;
data.f = 220.5;
cout << "data.f : " << data.f << endl;
strcpy( data.str, "C/C++ 语言");
cout << "data.str : " << data.str << endl;
return 0;
}
3、共用体的特点及用途
共用体的所有成员共享同一块内存, 每次只能安全访问一个成员,共用体的大小等于最大成员的大小,适合在内存有限或需要高效存储的场景使用。在字节和其他数据类型之间转换时很有用,还可以用于模拟硬件寄存器或处理协议数据。
#include <iostream>
using namespace std;
// 定义共用体
union Data {
int intValue; // 整型成员
float floatValue; // 浮点型成员
char charValue; // 字符型成员
};
int main() {
Data data; // 创建共用体变量
// 存储整数
data.intValue = 42;
cout << "Integer value: " << data.intValue << endl;
// 存储浮点数(覆盖整数)
data.floatValue = 3.14;
cout << "Float value: " << data.floatValue << endl;
// 存储字符(覆盖浮点数)
data.charValue = 'A';
cout << "Character value: " << data.charValue << endl;
// 注意:共用体成员共享内存,数据可能被覆盖
cout << "After storing character, Integer value: " << data.intValue << endl;
return 0;
}
4、共用体与结构体的区别
共用体(union
)和结构体(struct
)是两种数据结构,它们的主要区别在于内存的使用方式以及用途。
特性 | 结构体(struct) | 共用体(union) |
---|---|---|
内存分配 | 每个成员独立分配内存 | 所有成员共享同一块内存 |
大小 | 总大小是所有成员大小之和 | 大小等于最大成员的大小 |
访问成员 | 可以同时访问多个成员 | 任意时刻只能安全访问一个成员 |
使用场景 | 用于描述复杂数据结构 | 用于节省内存或实现多种数据形式 |
5、带构造函数和析构函数的共用体
C++11 开始,共用体可以包含非平凡类型(如 std::string
或类对象)。在这种情况下,需要手动管理构造函数和析构函数。
#include <iostream>
#include <string>
using namespace std;
union MixedData {
int i;
double d;
string s; // 需要手动管理
MixedData() { new(&s) string("Hello, Union!"); } // 初始化字符串
~MixedData() { s.~string(); } // 显式调用析构函数
};
int main() {
MixedData data;
cout << data.s << endl;
data.d = 3.14; // 写入 double,覆盖 string
cout << "Double: " << data.d << endl;
return 0;
}
6、内存布局和大小
共用体(union)中所有成员共享同一块内存。内存大小等于最大成员的大小,以确保能够存储共用体的任何成员。起始地址相同,所有成员的地址是相同的(它们共享起始地址)。改变一个成员的值会覆盖其他成员的值。共用体的大小受内存对齐规则的影响,通常为最大成员的大小和系统对齐要求的倍数。
#include <iostream>
using namespace std;
union Example {
int a; // 4 字节
double b; // 8 字节
char c[3]; // 3 字节
};
int main() {
cout << "Size of Example: " << sizeof(Example) << " bytes" << endl;
return 0;
}