[OC底层]联合体和位域

648 阅读3分钟

位域

位域可以使内存更加优化,有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。 位域是把一个字节中的二进制位分为几个不同的区域,并说明每个区域的位数. 例如存放一个布尔类型的变量时,只有01两种状态,用一位二进制位就行.看如下例子:

struct Car1 {
    BOOL front; // 0 1
    
    BOOL back;

    BOOL left;

    BOOL right;
};

// 位域方式存储
struct Car2 {
    BOOL front: 1;

    BOOL back : 1;

    BOOL left : 1;

    BOOL right: 1;
};

struct Car1 car1;
NSLog(@"size of car1: %ld", sizeof(car1));

struct Car2 car2;
NSLog(@"size of car2: %ld", sizeof(car2));

结果得到

2021-09-12 10:46:42.518223+0800 001-联合体位域[77845:1542384] size of car1: 4

2021-09-12 10:46:42.521262+0800 001-联合体位域[77845:1542384] size of car2: 1

我们可以看出位域存储更节省空间. 对于位域的定义,我们要遵循以下三点规则:

  • 1:一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct bs
{
 unsigned a:4
 unsigned :0 /*空域*/
 unsigned b:4 /*从下一单元开始存放*/
 unsigned c:4
}

在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

  • 2: 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。
  • 3: 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:
struct k
{
 int a:1
 int :2 /*该2位不能使用*/
 int b:3
 int c:2
};

下面来了解一下联合体;

联合体

当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的:

  • 1)联合体是一个结构;
  • 2)它的所有成员相对于基地址的偏移量都为0;
  • 3)此结构空间要大到足够容纳最"宽"的成员;
  • 4)其对齐方式要适合其中所有的成员; 看下面的例子来了解一下联合体结构体之间的区别:
  • 结构体:
struct Teacher1 {
    char *name;
    int  age;
};

struct Teacher1   teacher1;
teacher1.name = "Cooci";
teacher1.age  = 18;

加入断点查看成员变量的赋值情况:

Screenshot 2021-09-12 at 17.20.40.png

  • 在运行完第56行时,用p teacher1 查看赋值情况,输出为: (Teacher1) $0 = (name = "Cooci", age = 0)
  • 在运行完第57行时输出为: (Teacher1) $1 = (name = "Cooci", age = 18)

可以看出结构体里的成员变量都可以被正确的赋值

  • 联合体
union Teacher2 {
    char *name;
    int  age;
    double height ;
};

union Teacher2    teacher2;
teacher2.name = "Cooci";
teacher2.age  = 18;

加入断点查看成员变量的赋值情况:

Screenshot 2021-09-12 at 18.05.10.png

  • 在运行完第60行时,用p teacher2 查看赋值情况,输出为: (Teacher2) $0 = (name = "Cooci", age = 15932)
  • 在运行完第61行时输出为: (Teacher2) $1 = (name = "", age = 18) 从结果我们可以分析出虽然联合体的成员变量和结构体是一样的,但是结构体的成员变量是共存的,但共用体的成员变量是互斥的。struct特点就是全分配,不管用不用,而union特点就是只分配一个,对新的成员赋值,就会把原来成员的值覆盖掉,节省内存。

blog.csdn.net/ZhaiAlan/ar…