Union的妙用和注意
一块内存不同的访问方式
// 1.数组的便捷访问 // 一块内存两种等价的访问方式 template <typename T> union Mat4x4 { struct{ T m00, m01, m10, m11; }; T m[2][2]; }; int main(int argc, const char * argv[]) { Mat4x4<float> mat = {1,2,3,4}; std::cout<< mat.m00 <<std::endl; std::cout<< mat.m[0][0] <<std::endl; // output: 1 // 1 return 0; }
将变量拆成字节访问
int main(int argc, const char * argv[]) { union Int4 { struct { unsigned char _1, _2, _3, _4; }; int _int; }; Int4 integer; integer._int = 100000000; printf("%08X\n", integer._int); printf("%02X\n", integer._1); printf("%02X\n", integer._2); printf("%02X\n", integer._3); printf("%02X\n", integer._4); // output: // 05F5E100 // 00 // E1 // F5 // 05 return 0; }
判断CPU大小端问题
int big_endian (void) { union{ long l; char c[sizeof(long)]; }u; u.l = 1; return (u.c[sizeof(long) - 1] == 1); } int main(int argc, const char * argv[]) { //在大端格式中,字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中 //与大端存储格式相反,在小端存储格式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节 if(!big_endian()) { printf("CPU是小端模式\n"); } else { printf("CPU是大端模式\n"); } }
// 这样判断大小端更简洁 bool is_big_endian(void) { unsigned int test = 0xff000000; return (*(unsigned char *)&test == 0xff); }
Union的内存占用
首先内存占用肯定是要大于最大的一项,其次因为内存对齐的缘故
int main(int argc, const char * argv[]) { // # 内存问题 union Max { char _1; int _4; double _8; char _17[17]; }; printf("size: %lu\n", sizeof(Max)); // output: size: 24 return 0; }
使用注意
Union是C语言的东西,当然C++中也会有了,但是Union在C++中有些需要注意的地方。
由于union里面的东西共享内存,所以不能定义静态、引用类型的变量。
下面是错误的代码:
union Test { static int c; int &ref; };
C语言中没有类的概念,更没有构造和析构函数,Union中如果存在C++对象,那么C++对象必须不能存在构造和析构函数,
默认的构造和析构不会被调用,存C++对象指针是没问题的。
union TestUnion { class { public: //去掉注释会发生错误 //TestClass() { // printf("构造\n"); //} //~TestClass() { // printf("析构\n"); //} int var; } c; }; int main(int argc, const char * argv[]) { TestUnion t = {1}; printf("var: %d\n", t.c.var); return 0; }
所以,我们在C++中使用union时,尽量保持C语言中使用union的风格,尽量不要让union带有对象。
Published with Luweimy