位段:
位段的声明和结构是类似的 但还是有不同的
位段的成员必须是int,unsigned int,signed int 但这只是规定 char也没什么事
位段的成员名后边有一个冒号和数字
位段的内存分配:
- 位段的空间是按照需要以4个字节或者1个字节的方式来开辟的
- 位段涉及很多不确定的因素,位段是不跨平台的,注重可执行程序应该避免使用位段
位段很大的作用就是可以帮助我们优化 节省空间 有些变量只要那么多的bit位 我们就给他那么多 这样就可以很好的节省空间
#include <stdio.h> struct stu { char a:3; char b:4; char c:5; char d:4; }s; int main() { s.a=10; }
这种给有位段的结构体成员变量赋值时 也要注意位段的限制
好像这里给a赋值10 他的二进制码 1010 但是在赋值时 我们分配给a的是三个bit位 那么存放时就只能放三个bit位的值 也就是是说只能放 010 进去
对于连续存放时 从地位往高位 放入
位段的跨平台问题:
① int 位段被当成有符号数还是无符号数是不确定的
②位段中的最大数目不能确定(早期有些机器是是16位机器 最大数目是16 32位机器的最大数目是32)所以如果一个机器是16位的位段设置为 大于它的 就会出问题
③ 位段中的成员在内存中是从左向右分配 还是从右向左分配 这个也是没有定义的
④ 当一个结构体包括两个位段,如果第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃还是利用,这是不确定 (这就跟我们说的一样)
总的来讲 位段是不支持跨平台的
枚举类型:
枚举顾名思义 就是 列举 把一些数据列举出来
enum u { //枚举的可能取值 EXIT,0 这只是初始的 MON, 1 THE, 2 WED 3 }; enum s { DAY=7, ONE=6, 这时候FOR为7 FOR }; int main() { enum u d = EXIT; enum u d = 0;//这样赋值是不建议的 在c语言里面它可能没有报错 但在c++里面检查更严格后就会报错了 //因为c++会认为 d是枚举类型 0是int类型 不会让他们这样赋值 }
注意 枚举成员都是常量
枚举看起来虽然功能单一 但它也是有优点的
- 增加代码的可读性和可维护性
- 和#define定义的标识符比较枚举有类型 也就是说枚举有类型检查,更加严谨
- 防止了命名污染(封装)
- 便于调试
- 使用方便,一次可定义多个常量
联合体:
union u { char c; double i; }; int main() { printf("%d\n",sizeof(u)); 8 最大成员的大小 printf("%p\n",&u); printf("%p\n",&(u.c)); printf("%p\n",&(u.i)); //后面的地址是一样的 }
可以发现 c 和 i 的其实地址是一样的 使用的第一个字节重复了 所以联合体还有个名字叫共用体 当然共用体也有个缺点 就是同一时间只能使用一个变量 每次使用一个变量 另一个变量也会跟着改变所以 每次只能使用一个变量
所以联合体就有了一个应用场景 就是当你每次使用时 都会用到不同的东西 但每次只使用一个的时候 就可以用了
知道了这种特性后 我们就可以用这个特性来判断我们的机器是大端还是小端
int Checksys() { union u { char i; int c; }s; s.c=1; return s.i; }
联合体大小的计算:
联合的大小至少是最大成员的大小。
当最大成员的大小不是最大对齐数的整数倍时,就要对齐最大对齐数的整数倍
大家来计算一下这个联合体的大小是多少 union un { short c[7]; int i; };
union un { short c[7]; 2-8-2 int i; 4-8-4 }; 最终最大对齐数是4 也就是要4的倍数 其中最大成员大小是14 那么最终的联合体大小是16
那么到这里 我们自定义类型的讲解就没有了 感谢大家能看到这里 希望大家都能收到自己心仪的offer!!!!