C++ 与C联合体
什么是联合体(union)?
联合体(union)是C和C++中的一种特殊数据结构,它允许在相同的内存位置存储不同的数据类型。与结构体(struct)不同,联合体的所有成员共享同一块内存空间,这意味着一次只能使用一个成员变量。
备注
联合体的大小通常等于其最大成员的大小,因为它需要足够的空间来存储任何一个成员。
C语言中的联合体
在C语言中,联合体的基本语法如下:
union UnionName {
dataType1 member1;
dataType2 member2;
// ...
};
简单示例
#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: %f\n", data.f);
// 此时整数成员的值已被破坏
printf("data.i: %d\n", data.i);
// 使用字符串成员
sprintf(data.str, "C Programming");
printf("data.str: %s\n", data.str);
// 其他成员的值已被破坏
printf("data.f: %f\n", data.f);
printf("data.i: %d\n", data.i);
return 0;
}
输出结果类似于:
data.i: 10
data.f: 220.500000
data.i: 1129316352
data.str: C Programming
data.f: 1.4139e-33
data.i: 1094861636
C++ 中的联合体
C++继承了C的联合体概念,但添加了一些扩展特性:
- 在C++中,联合体可以包含构造函数、析构函数和成员函数
- C++11引入了"带标记的联合体"(tagged union)概念
- 现代C++中,
std::variant
提供了更安全的替代方案
C++ 中联合体的基本使用
#include <iostream>
#include <cstring>
union Data {
int i;
float f;
char str[20];
// C++允许在联合体中定义构造函数
Data() {
std::memset(str, 0, sizeof(str));
}
};
int main() {
Data data;
data.i = 10;
std::cout << "data.i: " << data.i << std::endl;
data.f = 220.5;
std::cout << "data.f: " << data.f << std::endl;
std::cout << "data.i: " << data.i << std::endl;
std::strcpy(data.str, "C++ Programming");
std::cout << "data.str: " << data.str << std::endl;
return 0;
}
C++ 11中的匿名联合体
C++11允许在类/结构体中定义匿名联合体:
#include <iostream>
#include <string>
struct Device {
enum Type { KEYBOARD, MOUSE, TOUCHPAD };
Type type;
// 匿名联合体
union {
struct {
int numKeys;
bool hasNumpad;
} keyboard;
struct {
int dpi;
bool wireless;
} mouse;
struct {
float width;
float height;
bool multiTouch;
} touchpad;
};
};
int main() {
Device dev;
dev.type = Device::MOUSE;
dev.mouse.dpi = 1200;
dev.mouse.wireless = true;
std::cout << "设备类型: " << dev.type << std::endl;
if (dev.type == Device::MOUSE) {
std::cout << "DPI: " << dev.mouse.dpi << std::endl;
std::cout << "是否无线: " << (dev.mouse.wireless ? "是" : "否") << std::endl;
}
return 0;
}
C++ 与C联合体的主要区别
特性 | C语言联合体 | C++联合体 |
---|---|---|
成员函数 | 不支持 | 支持 |
静态成员 | 不支持 | 支持 |
引用成员 | 不适用 | 不允许 |
具有构造函数/析构函数的类成员 | 不适用 | C++11之前不允许,C++11之后允许 |
匿名联合体 | 支持但有限制 | 完全支持,且可以在类内部使用 |
继承 | 不支持 | 支持但很少使用 |
警告
C++17之前,联合体成员不能包含非平凡构造函数、非平凡拷贝赋值运算符、非平凡析构函数的类类型。从C++17开始,这些限制被取消了。
在C和C++混合代码中使用联合体
当在混合C和C++的项目中使用联合体时,需要注意以下几点:
- 确保联合体定义在两种语言下兼容
- 注意内存对齐差异
- C++的高级特性在C中不可用
兼容性示例
假设我们需要定义一个在C和C++中都能使用的联合体:
// shared_header.h
#ifdef __cplusplus
extern "C" {
#endif
typedef union SharedData {
int i;
float f;
char str[20];
// C++特有的成员函数应该放在条件编译块中
#ifdef __cplusplus
void clear() {
memset(str, 0, sizeof(str));
}
#endif
} SharedData;
// 可以在C和C++中共同使用的函数
void print_shared_data(SharedData* data);
#ifdef __cplusplus
} // extern "C"
#endif
// cpp_file.cpp
#include "shared_header.h"
#include <iostream>
int main() {
SharedData data;
data.i = 42;
// 使用C++特有的成员函数
data.clear();
// 调用共享函数
print_shared_data(&data);
return 0;
}
// c_file.c
#include <stdio.h>
#include "shared_header.h"
void print_shared_data(SharedData* data) {
printf("Integer value: %d\n", data->i);
printf("Float value: %f\n", data->f);
printf("String value: %s\n", data->str);
}