联合体
定义
联合体也叫共用体,由不同的数据类型组成,其变量互斥,存储方式是所有成员共用一个段内存,共同体同一时刻只能保存一个成员的值,如果对新的成员赋值,就会将原来成员的值覆盖掉。
特性
- 在
union
中,分配内容空间大小,等于占用内存最大的数据类型字节大小 - 共享一段内存,成员变量的赋值操作,其他成员变量原有数据将成为脏数据,不可用。
例子
// 联合体的定义
union Teacher {
char *name; // 8
int age; // 4
double height; // 8
};
- 验证联合体大小
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
可证明联合体的大小,是由占用内存最大的数据类型字节大小决定
- 验证是否共用同一片地址
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
可验证联合体中成员变量使用同一个地址
- 验证一个成员被赋值,其他成员数据不可用
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 联合体
union Teacher teacher;
teacher.name = "AngaoTu";
teacher.age = 18;
teacher.height = 175.0;
}
return 0;
}
打印结果:
- (Teacher) teacher = (name = "AngaoTu", age = 16176, height = 2.1220037829711594E-314)
- (Teacher) teacher = (name = "", age = 18, height = 2.1219957998584539E-314)
- (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】
特性说明
- 当相邻成员,如果它们的位宽之和小于类型的
sizeof
大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始,其偏移量为类型大小的整数倍。 - 位域的宽度不能超过它所依附的数据类型的长度,成员变量都是有类型的,这个类型限制了成员变量的最大长度,: 后面的数字不能超过这个长度。
- 位域可以是无名位域,这时它只用来作填充或调整位置。无名的位域是不能使用的
联合体位域
定义
把联合体和位域结合起来的数据类型,称为联合体位域
声明
union isa_t {
uintptr_t bits;
#if defined(ISA_BITFIELD)
struct {
ISA_BITFIELD; // defined in isa.h
};
Class cls;
};
- 由于
isa_t
是一个共用体,所以bits
和cls
共用一块内存空间。 -
bits
是一个位域,里面根据不同位定义了数据,节省空间。
网友评论