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带有对象。

 

posted @ 2014-11-24 20:33  luweimy  阅读(632)  评论(0编辑  收藏  举报