C语言: 关于位段的学习

一.什么是位段:

位段的声明与结构是类似的,有两个不同:

位段的成员必须是intusigned int或者signed int等整型家族的
位段的成员名后面有一个冒号和一个数字

struct A

{

int _a : 2;

int _b : 5;

int _c : 10;

int _d : 30;

};

int main()

{

printf("%d\n", sizeof(struct A));

return 0;

}

都是int类型的数据那么先开辟一个整型4byte的空间

int _a : 2;表示给结构体成员_a开辟了2个比特位的内存空间;

int _b : 5;表示给结构体成员_b开辟了5个比特位的内存空间;

int _c : 10;表示给结构体成员_c开辟了10个比特位的内存空间

目前为止已经使用了32个比特位中的17个;还剩下15个;

int _d : 30;表示给结构体成员_d开辟30个比特位的内存空间

显然开辟4byte是不够的那么再次开辟一个整形4byte的空间;

这个时候_d使用的是新开辟的空间而不是首次开辟使用剩余的空间 所以造成第一个4byte15bit的浪费;

最终计算sizeof(struct A)的大小是8byte;

虽然依旧存在一些浪费空间但是相比4个整形的16byte已经是节省了一半的空间了;

二.位段的内存分配

1.位段的成员可以是int unsigned int signed int或者是char(属于整形家族)类型

2.位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的。

3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

注意:位段只能在结构体中使用,可以在一定程度上减少空间的浪费;

一般情况包含位段的结构体里面都是同一类型的数据,如果多种类型数据复合会将程序复杂化而且 它本身是不稳定的;

冒号后面数字的大小不能超过类型的大小int(32)char(8);

三.位段的跨平台问题

1. int位段被当成有符号数还是无符号数是不确定的.(只有在位段中是不确定的);

2位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。

3.位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4.当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。

位段内存分配没有明确规定,取决于编译器,不同编译器实现的方式不同。在VS2022中,位段成员是从右往左分配内存的,并且如果遇到一个字节中的内存不够时,则会抛弃剩余内存,重新开辟一个字节的内存再分配

总结:

跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,

但是有跨平台的问题存在。

四.位段使用的注意

不能对位段的成员进行&操作;

位段允许几个小的数据类型合并在一起,这样有的成员的起始位置就不是某个字节的起始位置,在内存中为每个字节分配一个地址,一个字节内部的 bit位是没有地址

既然不能使用&操作符,那么怎么对位段中的成员赋值呢

可以值存入一个变量中,再将变量的值赋给位段中的成员

#include <stdio.h>

struct S

{

char a : 5;

int b : 16;

};

int main()

{

struct S s = { 0 };

//scanf("%d", &s.a); 这是错误的



//正确示范

int n = 0;

scanf("%d", &n);

s.a = n;

return 0;

}

五.位段的应用

有些数据只需少量bit的内存空间,位段允许几个数据类型合并在一起,节约了存储内存,⽹络传输的数据包大小也会较小些,传输数据时的网络较为通畅;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值