美文网首页
联合体与位域

联合体与位域

作者: 祀梦_ | 来源:发表于2022-12-06 20:25 被阅读0次

    联合体

    定义

    联合体也叫共用体,由不同的数据类型组成,其变量互斥,存储方式是所有成员共用一个段内存,共同体同一时刻只能保存一个成员的值,如果对新的成员赋值,就会将原来成员的值覆盖掉。

    特性

    1. union中,分配内容空间大小,等于占用内存最大的数据类型字节大小
    2. 共享一段内存,成员变量的赋值操作,其他成员变量原有数据将成为脏数据,不可用。

    例子

    // 联合体的定义
    union Teacher {
        char *name; // 8
        int age; // 4
        double height; // 8
    };
    
    1. 验证联合体大小
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // 联合体
            union Teacher teacher;
            teacher.name = "AngaoTu";
            teacher.age = 18;
            teacher.height = 175.0;
            
            NSLog(@"联合体大小 size = %lu", sizeof(teacher));
            
        }
        return 0;
    }
    

    打印结果:2022-07-30 15:38:42.149406+0800 联合体+位域[9304:21445471] 联合体大小 size = 8

    可证明联合体的大小,是由占用内存最大的数据类型字节大小决定

    1. 验证是否共用同一片地址
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // 联合体
            union Teacher teacher;
            teacher.name = "AngaoTu";
            teacher.age = 18;
            teacher.height = 175.0;
            
            NSLog(@"name 地址 = %p, age 地址 = %p, height 地址 = %p", &teacher.name, &teacher.age, &teacher.height);
        }
        return 0;
    }
    

    打印结果:2022-07-30 15:43:05.950276+0800 联合体+位域[10267:21450499] name 地址 = 0x7ffeefbff398, age 地址 = 0x7ffeefbff398, height 地址 = 0x7ffeefbff398

    可验证联合体中成员变量使用同一个地址

    1. 验证一个成员被赋值,其他成员数据不可用
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // 联合体
            union Teacher teacher;
            teacher.name = "AngaoTu";
            teacher.age = 18;
            teacher.height = 175.0;
        }
        return 0;
    }
    

    打印结果:

    1. (Teacher) teacher = (name = "AngaoTu", age = 16176, height = 2.1220037829711594E-314)
    2. (Teacher) teacher = (name = "", age = 18, height = 2.1219957998584539E-314)
    3. (Teacher) teacher = (name = "", age = 0, height = 175)

    可验证成员变量的赋值操作,其他成员变量原有数据将成为脏数据,不可用

    优缺点

    • 优点:
      • 内存使用更为精细、节省空间
    • 缺点:
      • 不够包容,成员之间会互相影响

    位域

    定义

    有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。 例如在存放一个开关量时,只有 0 和 1 两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。

    声明

    • 位域的定义和结构体的定义相仿
    sturct 位域结构名 {
      位域列表 // 格式: [类型 位域名:位域长度]
    };
    
    struct bits {
        int a: 8;
        int b: 2;
        int c: 6;
    }
    

    位域的大小

    struct bits {
        char a:2; 
    };
    // size = 1 
    
    struct bits {
        char a:2; 
        char b:2;
    };
    // size = 1 
    
    struct bits {
        char a:2; 
        char b:2;
        char c:4; 
        char d:4;
    };
    // size = 2
    
    struct bits {
        int a:4;
    };
    // size = 4 
    
    struct bits {
        int a:4;
        int b:4;
    };
    // size = 4
    
    struct bits {
        char a:8; 
        char b:8; 
        char c:8; 
        char d:8; 
        int e:4;
    };
    // size = 8 
    
    • 位域的存储同样遵循结构体内存对齐规则
      • 选取该位域结构内声明时的类型中长度最大的类型长度,为对齐方式
      • 具体可参考结构体内存对齐【TODO】

    特性说明

    1. 当相邻成员,如果它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始,其偏移量为类型大小的整数倍。
    2. 位域的宽度不能超过它所依附的数据类型的长度,成员变量都是有类型的,这个类型限制了成员变量的最大长度,: 后面的数字不能超过这个长度。
    3. 位域可以是无名位域,这时它只用来作填充或调整位置。无名的位域是不能使用的

    联合体位域

    定义

    联合体位域结合起来的数据类型,称为联合体位域

    声明

    union isa_t {
        uintptr_t bits;
    #if defined(ISA_BITFIELD)
        struct {
            ISA_BITFIELD;  // defined in isa.h
        };
        Class cls;
    };
    
    • 由于isa_t是一个共用体,所以bitscls共用一块内存空间。
    • bits是一个位域,里面根据不同位定义了数据,节省空间。

    相关文章

      网友评论

          本文标题:联合体与位域

          本文链接:https://www.haomeiwen.com/subject/tndgfdtx.html