在C++中,某些信息的存储不需要占用到整个字节或者整个int的空间,而只需要一位或者几位来表示即可,为了减少信息的传输量同时节省存储空间,可以将多个总大小不超过4byte或8byte等类似的信息用一个int(32位机器)或者long long来表示,这就导致了在解析过程中的一些麻烦,位域则很好的解决了这个问题,简单使用不再赘述,使用过程中需要注意一些问题,在此记录并不断更新遇到的新问题。
- 无名用于填充和调整位置,宽度为0的位域强制下一位域对齐到下一type边界
struct test{
int a:8;
int : 0;
int b:8;
};//输出size为8
- 位域长度不能大于指定类型的长度
struct test{
int a:40;
int b:10;
};//编译出错
有文章说以上会出现编译出错,但本人在ubuntu16.04下用gcc5.4.0可以编译通过,但copy一个64位数据进test对象时,a会截取其前32位数据输出,而b会取41-50位的数据进行输出,其中33-40位的数据将被舍弃,其结果与:
struct test{
int a:32;
int : 8;
int b:10;
};
相同,因此最好按照下面的写法来写,不要让位域长度超出其类型长度。
- 相邻位域类型不同时,各编译器具体实现有差异
例如:
struct test{
bool a:1;
int b:10;
};
极其不推荐使用不同类型混合使用,实测会出现各种诡异的情况,不同编译器的输出结果不同,很容易造成程序混乱
- 如果相邻位域字段的类型相同,但其位宽之和小于类型的大小,则后面的位域字段紧邻前一字段存储
struct test{
int a:1;
int b:8;
};
总大小为4byte,b会取2-9位数据
- 如果相邻位域字段的类型相同,但其位宽之和大于类型的大小,则后面的位域字段将从新的存储单元开始,其起始偏移量为类型大小的整数倍
struct test{
int a:1;
int b:32;
};
总大小为8byte,且b会取33-64位数据
综上所述,使用位域最推荐的方法是所有字段使用同样的的无符号类型,其总长度最好为该类型的整数倍,对于不需要的位用无名字段填充,字段长度不要超过类型长度,例如:
struct test{
uint_64 a:1;
uint_64 b:16;
uint_64 :15;
uint_64 c:32;
uint_64 d:32;
};
在实际使用时自行进行相应的转换。