位段
- 位段与结构体类似,不同点如下
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字。
struct A{
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};
- 其中冒号后的数字的单位为比特位,即_a所占空间为 2 个比特位
位段内存空间分配
- 位段的成员可以是 int unsigned int signed int 或者是 char(属于整形家族)类型
- 位段的空间上是按照需要以 4 个字节( int )或者 1 个字节( char )的方式来开辟的。
- 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(struct A));
运行结果如下
不难发现,位段 A 所占内存空间大小为 8 个字节,即两个 int 所占空间大小
struct S{
char a : 3;
char b : 4;
char c : 5;
char d : 4;
};
- 位段 S 在vs编译器内的空间开辟,是从高地址向低地址开辟,先在第一个字节的高地址内开辟3个比特位给 a,因低地址剩余5个字节的空间,足够存放 b,因此开辟4个比特位给b,a和b占同一个字节,在新一个字节空间里开辟5个比特位给 c,因高位仅剩3个比特位,无法容纳d,因此 d重新在新一个字节内开辟4个比特位的地址存放,具体如下:
int main() {
struct S s = { 0 };
s.a = 10; // 1010
s.b = 12; // 1100
s.c = 3; // 0011
s.d = 4; // 0100
return 0;
}
进行赋值,多余的位数被省略,如是 s.a = 10 存进内存只存后三位 010,结果如下
在内存中,以十六位形式存放,结果如下
枚举
当我们需要对一个事物的可能取值一一列举时,便使用枚举,如下
// 星期
enum Day{ //enum Day枚举类型
Sun, // 枚举常量
Mon,
Tues,
Wed,
Thur,
Fri,
Sat
};
- 枚举是有默认取值的,默认从0开始,一次递增1
int main() {
enum Day d7 = Sat;
printf("%d\n", d7);
return 0;
}
运行结果如下
当我们对Sun进行初始化为1后,
enum Day{
Sun=1,
Mon,
Tues,
Wed,
Thur,
Fri,
Sat
};
int main() {
enum Day d7 = Sat;
printf("%d\n", d1);
return 0;
}
运行结果如下
枚举优点
- 增加代码的可读性和可维护性
- 和#define定义的标识符比较枚举有类型检查,更加严谨。
- 防止了命名污染(封装)
- 便于调试
- 使用方便,一次可以定义多个常量
联合
- 联合又称为共用体
- 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间
union Un{
char c;
int i;
int i2;
int i3;
};
int main() {
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));
return 0;
}
运行结果如下
- 联合Un 大小为4个字节
int main() {
union Un un;
// 打印地址
printf("%p\n", &un);
printf("%p\n", &(un.c));
printf("%p\n", &(un.i));
printf("%p\n", &(un.i2));
printf("%p\n", &(un.i3));
return 0;
}
运行结果如下
- 因此可知,所有的成员都公用同一块地址空间,一个联合变量的大小,至少是最大成员的大小
联合在判断大小端的应用
int check_sys() {
union Un {
char c;
int i;
}u;
u.i = 1;
return u.c;
}
int main() {
if (1 == check_sys()) {
printf("小端\n");
}
else {
printf("大端\n");
}
return 0;
}
- u.i=1 在小端存储模式中,存放为 01 00 00 00,因为 u.c 与 u.i 存放在同一空间。取 u.c 时,取前两个比特位,得到 01
联合大小计算
- 联合的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍
union Un1
{
char c5[5];
int i;
};
union Un2
{
short c7[7];
int i;
};
- Un1最大成员大小为 5,c5、i的对齐数分别为1、4,所以联合体Un1的大小是最大对齐数 4 的整数倍,即8
- Un2最大成员大小为 14,c7、i的对齐数分别为2、4,所有联合体Un2的大小是最大对齐数 4 的整数倍,即16
int main() {
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
return 0;
}
运行结果如下