位域
位域可以使内存更加优化,有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。 位域是把一个字节中的二进制位分为几个不同的区域,并说明每个区域的位数. 例如存放一个布尔类型的变量时,只有0和1两种状态,用一位二进制位就行.看如下例子:
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;
加入断点查看成员变量的赋值情况:
- 在运行完第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;
加入断点查看成员变量的赋值情况:
- 在运行完第60行时,用
p teacher2查看赋值情况,输出为:(Teacher2) $0 = (name = "Cooci", age = 15932) - 在运行完第61行时输出为:
(Teacher2) $1 = (name = "", age = 18)从结果我们可以分析出虽然联合体的成员变量和结构体是一样的,但是结构体的成员变量是共存的,但共用体的成员变量是互斥的。struct特点就是全分配,不管用不用,而union特点就是只分配一个,对新的成员赋值,就会把原来成员的值覆盖掉,节省内存。