位段的声明和结构是类似的,有两个不同:
int
、unsigned int
或signed int
//结构体
struct A {
int a;
int b;
int c;
int d;
};
//位段
struct B{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
sizeof
去计算一下这个结构体的大小printf("结构体大小:%d\n", sizeof(struct A));
printf("位段大小:%d\n", sizeof(struct B));
可以看到,结构体的大小是16,位段是8,二者为何会存在区别呢?原因在于这个: 2
吗?
47b
,在内存中1B = 8b
,要存下这个47个比特位的话应该6个字节就够了,但是结果为什么是8呢?我们不得而知学习了位段的相关知识后你就知道了
首先来科普一下位段的相关知识
[int]
或者1个字节 [char]
的方式来开辟的。_a
占了2个比特位,还剩下【30b】_b
占了5个比特位,还剩下【25b】_c
占了10个比特位,还剩下【15b】_d
占了30个比特位,但是剩下的【15b】不够用了,此时编译器会继续开辟出4B,也就是32b的空间来存放4 + 4 = 8B
struct B{
//4Byte - 32bit
int _a : 2; //30
int _b : 5; //25
int _c : 10; //15
//4Byte - 32bit
int _d : 30;
//4 + 4 = 8
};
看了我上面的这样计算,你一定会有这些疑问
第一次是32b用剩后的【15b】去哪儿了呢?
_d
使用的是【15b】+ 后面开辟出来的32b,还是只用到后面的32b呢?
难道所有平台都是这样吗?有没有不一样的计算方法?
接下去我就通过对位段进行分析,然后观察内存分布来揭晓上面究竟是如何计算的。
为了方便期间,这里换一组位段,但是换汤不换药
struct S
{
char a : 3;
char b : 4;
char c : 5;
char d : 4;
};
int main(void)
{
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
return 0;
}
char
类型的,所以编译器会首先为其分配一个字节的空间,然后随着变量的存入,最终是需要三个字节然后我们来逐一分析一下
a
放完后就是b
,占4个比特位,但是放c
的时候就放不下了,所以需要在开辟1个字节的空间,此时d
再来放的话也放不下了,所以也要再开辟1个字节 ,最后也就需要3个字节的空间a
的初始值为10,不过这是十进制,转换为二进制形式的话就是[1010]
,转看位段这里a变量的是占了3位,所以会截断成010
,将它放到第一个字节处的右边3个比特位处b
,初始值为12
,转换为二进制形式的话就是[1100]
,而b在内存中也刚好是占4个比特位的大小,刚好第一个字节处还可以放得过,所以继续顺位放置c
,初始值为3
,转换为二进制形式的话就是11
,但是c在内存中也占5个比特位的大小,所以要在前面做一个扩充便为[00011]
,但是第一个字节放不下了,上面放了【3】+【4】=【7】,只剩下1个比特位,那我们考虑再开一个字节的空间,为了保持连续性就直接把这个5个比特位的数据放到第二个字节的右边d
,初始值为4
,转换为二进制形式的话就是100
,不过d在内存中也占4个比特位的大小,所以要在前面补上一个0,即为[0100]
,但是第二个字节也放不过了,只剩三个比特位了,所以我们考虑再开一个字节的空间,然后放这个d上面只是我假设的编译器执行思维,不过真正是怎样的,我们还是要求证一下
01100010
即为——>0x62
00000011
即为——>0x03
00000100
即为——>0x04
62 03 04 cc
。来通过【内存】观察一下吧看完了上面这个,相信你对一开始的那个位段如何去进行求解的整个流程应该是非常清楚了,留给读者自己的分析观察
接下去我们再来讲讲有关位段的跨平台的问题
总结:跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在
a
只可能有【0】【1】【2】【3】这四种取值,那么只需要2个比特位就可以表达这四个数字了,即【00】【01】【10】【11】,那我们便可以使用位段来是实现:2
,但若是放在普通结构体中的话就只能是一个整型4个字节32个比特位的大小,这也就浪费了很多的空间b
也只有5种表示形式的话,5个比特位就够了,c
、d
也是一样。那么这个时候位段就派上用场了,若是使用结构体的话就会浪费掉很多的空间。所以我们前面在看的时候,结构体所占的空间大小是16B,而位段只有8B清楚了位段的相关知识和使用后,可能还是有同学比较迷惑这个位段到底是用来干嘛的,有什么实际应用场景吗?我们来看看
呵呵
只是里面的一个数据部分,还存在其他很多的字段,这些字段都占有各自的字节数最后来总结一下本文所学习的内容
以上就是本文要介绍的所有内容,感谢您的阅读,如果觉得有帮助的话,可以给个三连哦❤️❤️❤️