C++使用位域时如何获取位域成员的起始位与结束位编号
关于C++位域起始/结束位获取的问题解答
首先明确:C++标准不存在内置语法或标准库函数可以直接获取位域的起始/结束比特位。
根本原因
C++标准中位域的内存布局属于实现定义行为,仅约定了同类型的相邻位域会尽可能打包到同一个地址单元中,但是以下规则完全由编译器决定:
- 位域在地址单元中的排列顺序(大端架构通常从高位开始分配,小端架构通常从低位开始分配)
- 位域之间的填充位规则
- 跨地址单元的位域对齐规则
你问题中假设temp.b从第2位开始仅为特定编译器、特定编译配置下的结果,不是C++标准规定的必然行为。
特定场景下的替代实现方案
如果你仅在固定编译器、固定编译配置的场景下使用,可以通过自定义宏实现你要的效果,示例实现如下:
// 获取位域起始位(从0计数) #define BITFIELD_START(struct_type, field) ({ \ struct_type temp = {0}; \ temp.field = (typeof(temp.field))~0; \ unsigned char* buf = (unsigned char*)&temp;\ int bit_cnt = sizeof(temp) * 8; \ int start = 0; \ for(; start < bit_cnt; start++) { \ if(buf[start/8] & (1 << (start%8))) { \ break; \ } \ } \ start; \ }) // 获取位域结束位(从0计数) #define BITFIELD_END(struct_type, field) ({ \ struct_type temp = {0}; \ temp.field = (typeof(temp.field))~0; \ unsigned char* buf = (unsigned char*)&temp;\ int bit_cnt = sizeof(temp) * 8; \ int end = bit_cnt - 1; \ for(; end >= 0; end--) { \ if(buf[end/8] & (1 << (end%8))) { \ break; \ } \ } \ end; \ })
使用示例:
int b_start = BITFIELD_START(struct my_struct, b); // 返回值为2 int b_end = BITFIELD_END(struct my_struct, b); // 返回值为8
注意事项
- 上述实现仅适用于当前编译器的布局规则,更换编译器、编译选项或者目标架构后结果可能发生变化,可移植性极差
- 如果你的需求是做序列化、协议解析等场景,建议直接手动通过位掩码、位运算操作对应比特位,不要依赖位域的内存布局
内容的提问来源于stack exchange,提问作者Waad
相关产品推荐
相关产品推荐

