目录
位段
我们都知道结构体,那您是否了解位段呢?
仔细观察一下两个不一样的“结构体”,他们有什么区别呢?
一、位段的定义
位段的声明和结构体是类似的,但是有两点不同:
1.位段的成员必须是int、unsigned int、signed int或char(char属于整型家族)类型。(一般情况下位段的成员类型都全部为int或者char类型)
2.位段成员的后面有一个:(冒号)和一个数字(数字表示这个成员所需内存大小,以bit为单位)。
如上面的H就是一个位段。
二、位段的内存分配
位段的空间是以4个字节(位段成员是int类型)或者1个字节(位段成员是char类型)开辟的。(所以冒号后面的bit大小不会超过32bit(int类型)或8bit(char类型),具体还是要看机器(如16位机器int是2字节,32位机器int是4字节))
如下面G这个位段:
struct G
{
int i : 2;
int o : 5;
int p : 10;
int u : 30;
};
i占2bit,o占5bit,p占10bit,u占30bit,加起来应该是47bit,按道理6字节的空间就够存储他们了。
可事实并非如此:
经实践认证此位段所占空间为8字节,为什么呢?
下面我们来对此位段空间的分配进行详解:
由于此位段成员类型都是int,所以每次以4个字节(也就是32bit)为单位开辟空间:
以小段存储为例,我们先开辟32bit的空间:
再将只占2bit的i成员先存入:
接着紧按着i成员,将5bit的哦成员存入(段位没有像结构体一样的内存对齐):
之后再将10bit空间的p成员存入:
最后我们在存30bit的u成员时,发现内存只剩15bit不够用,此时我们再向空间申请4字节(int类型)的空间:
存入30bit的p成员:
在我们存完所有成员之后,我们发现实际存p时系统并不会再使用上面并未用完的15bit的空间,而是直接在可以存下p的新空间地方存p。
这就最终造成了段位G所占用的空间为64bit(8字节)。
三、段位赋值问题
现在我们将位段赋值:
int main()
{
unsigned char puc[4];
struct tagPIM
{
unsigned char ucPim1;
unsigned char ucData0 : 1;
unsigned char ucData1 : 2;
unsigned char ucData2 : 3;
}*pstPimData;
pstPimData = (struct tagPIM*)puc;
memset(puc,0,4);//将数组puc的4个字节全部赋值为0
pstPimData->ucPim1 = 2;
pstPimData->ucData0 = 3;
pstPimData->ucData1 = 4;
pstPimData->ucData2 = 5;
printf("%02x %02x %02x %02x\n",puc[0], puc[1], puc[2], puc[3]);
return 0;
}
我们先来模拟展示一下位段tagPIM的存储结构:
如图位段tagPIM的总存储大小为16bit,其中ucPim1占8bit、ucData2占3bit、ucData占2bit、ucData0占1bit。
而字符数组puc的存储结构为:
如图char元素0、1、2、3分别占8bit,一共32bit。
所以将puc强转为段位tagPIM指针类型时(pstPimData = (struct tagPIM*)puc),pstPimData最多可以指向puc字符数组中0和1元素大小的空间。
当puc中所以元素都被赋值为0时:
当pstPimData->ucPim1 = 2时,即ucPim1指针大小的空间被赋值为2时,2的二进制表示是10,puc中的元素发生如下变化:
当pstPimData->ucData0 = 3时,即ucData0指针大小的空间被赋值为3时,3的二进制表示是11,可是ucData0大小只有1bit,所以舍弃前一位,puc中的元素发生如下变化:
当 pstPimData->ucData1 = 4时,即ucData1指针大小的空间被赋值为4时,4的二进制表示是100,可是ucData1大小只有2bit,所以舍弃前一位,puc中的元素发生如下变化:
当pstPimData->ucData2 = 5时,即ucData2指针大小的空间被赋值为5时,5的二进制表示是101,可是ucData2的大小正好是3bit,所以不用舍弃,puc中的元素发生如下变化:
最终进行printf打印时puc【0】的值为10换为十六进制为2,puc【1】的值为101001转换为十六进制为29,puc【2】和puc【3】的值还为0。
四、位段跨平台问题
1.int位段被当成有符号数还是无符号数是不确定的。
2.位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题)。
3.位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4.当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
所以说跟结构体相比位段可以达到相同的效果而且比较节省空间,但是有跨平台的问题存在。
五、位段的运用
位段通常会运用在网络数据的封装(浅浅提一下~):
好了,今天的博客又要和大家说再见了,谢谢各位看官嘞!