//二、————位段(位段是通过结构体来实现的)只可用于结构体
2.1 什么是位段
位段的声明和结构是类似的,有两个不同:
1.位段的成员必须是(整型家族) int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字(数字大小不可以超过对应类型的比特位)。
3.位段是可以用来节省空间的
//#include<stdio.h>
//struct A//A就是一个位段类型。
//{
//?? ?//int为4字节=32比特位,但是_a只需两个比特位
//?? ?int _a : 2;//_a是成员名字
//?? ?int _b : 5;//:2表示其前面的成员只占两个比特位(或者说是给_a分配两个比特位)
//?? ?int _c : 10;//当成员的取值范围是非常有限的情况下,那我们所需要的内存空间也就可以一定程度上减小
//?? ?int _d : 30;
//};
//int main()
//{
//?? ?printf("%d\n", sizeof(struct A));
//?? ?return 0;
//}
那位段A的大小是多少?
由于成员类型为int,所以每次开辟4字节,而a,b,c,d共占用47个字节。
47>32字节,所以需要开辟新的空间来存放,因此大小为8字节
2.2 位段的内存分配
1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
2. 位段的空间上是按照需要以每次4个字节( int )或者每次1个字节( char )的方式来开辟的。
3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植性的程序应该避免使用位段。
//#include<stdio.h>
//struct S
//{
//?? ?char a : 3;
//?? ?char b : 4;
// ? ?char c : 5;
//?? ?char d : 4;
//};
//int main()
//{
//?? ?struct S s = { 0 };
//?? ?printf("%d\n",sizeof(struct S));
//?? ?s.a = 10;//转成二进制为:1010,由于a只需要4个比特位,所以由低到高截断为010
//?? ?s.b = 12;//转成二进制为:1100
//?? ?s.c = 3;//转成二进制为:101,由于a只需要5个比特位,所以补0为00101
//?? ?s.d = 4;//转成二进制为:100,由于a只需要4个比特位,所以补0为0100
//?? ?return 0;
//}
空间是如何开辟的?两个char即两个字节=16比特位
内存排布(由低到高—>从左向右)为(以小端排序排布):
高地址 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?低地址
?01100010 00000011 0000000 00000000 ?值为:14200600000(10进制)
?0x62030000十六进制为24c(每四个2进制位为一个16进制位)
2.3 位段的跨平台问题
1. int 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题)
3. 位段中的成员在内存中从是左向右分配,还是从右向左分配尚未定义(也要考虑大小端问题)
? 即,在内存中的排布顺序未定义,在不同环境下是不同的。
4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的比特位时,是
? 舍弃剩余的位还是利用,这是不同编译器下是不确定的。
总结:跟结构体相比,位段可以达到同样的效果(如果设计成位段式的这种结构,
// ? ? ? ?能够达到结构体想要的效果的话,位段是可以节省更多空间的)但是有不可跨平台的问题存在。
注意:位段这个语法的设计本身是不可跨平台的,但是我们能写出带有跨平台性的代码(针对不同的平台写出不同的代码)
4.———— 位段的应用(多用在网络中)