52. 类型双关union
目录
52.1 类型双关
52.2 union
52.1 类型双关
将一个int类型转为double类型,有如下方式
int main() {
int a = 5;
double b = a;//隐式类型转换
double c = (double)a;//显示类型转换
double d = *(double*)&a;//类型双关:将类型int的内存操作为double
//打印a 5 b:5 c:5 d:-9.25596e+61
std::cout << "a " << a << " b:" << b << " c:" << c << " d:" << d << std::endl;
std::cin.get();
}
可以看到,类型双关的操作先把一个int类型指针转为double类型指针,然后解引用。结果是在原来的int内存之后继续了4个字节,然后获取整个内存,结果打印的地址并不理想,有可能造成崩溃,这样的类型双关操作不安全。下面演示安全的类型双关操作:
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
struct Entity
{
int x, y;
int* getStartPosition()
{
return &x;
}
};
int main() {
Entity e = { 1,2 };
//方式一
int* position = (int*)&e;//结构体转为数组
std::cout << position [0]<< ","<<position[1] << std::endl;//打印1,2
//方式二
int* position2 = e.getStartPosition();
std::cout << position2[0] << "," << position2[1] << std::endl;//打印1,2
int y = *(int*)((char*)&e + 4);//通常使用y = e.y;来访问
std::cout << y << std::endl;//打印2
std::cin.get();
return 0;
}
可以看到我们能够自如的操作c++的内存,同一块内存进行不同类型之间的转换,这就是类型双关。需要做的就是将原来的指针转换为另一个类型的指针(结构体e的指针转化为数组的起始指针),然后作为另一种类型去访问它(作为数组类型去访问)。
52.2 union
union关键字使得不同类型成员变量共享同一块内存,这运用了类型双关的概念
//
// main.cpp
// HelloWorld
//
// Created by on 2024/11/28.
//
#include <iostream>
struct vector2
{
float x, y;
};
struct vector4 {
union {
struct
{
float x, y, z, w;
};
struct
{
vector2 a, b;//a对应x,y;b对应z,w
};
};//union中的各个成员占用同一块内存
};
void printVector2(const vector2 &v)
{
std::cout << v.x << "," << v.y << std::endl;
}
int main(int argc, const char * argv[]) {
vector4 v = { 1.0f,2.0f,3.0f,4.0f };
printVector2(v.a);
printVector2(v.b);
v.z = 5;
std::cout << "-------------" << std::endl;
printVector2(v.a);
printVector2(v.b);
}
打印结果如下: