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; }