我们说我的C结构定义为
struct data {
/* some memebers */
int flag_a:1;
int flag_b:1;
int flag_c:1;
/* some other members */
}
有没有办法利用在内存中表示为单个int的位域,并将条件s.flag_a | s.flag_b | s.flag_c
写为更简单的表达式,例如s.flags
?
或者像GCC这样的智能编译器能够实际推断它吗?
编辑:为了让自己绝对清楚:我正在寻找一种可移植的方式来测试所有正在设置的标志,而不是分别明确地测试每个标志。
答案 0 :(得分:7)
这不可能以任何确定的方式进行移植。问题是C标准不能保证这些位的任何内容:你不能知道哪个位是LSB,也不知道是否有填充。最重要的是,endianess也是一个问题。 (理论上,不同的签名格式。)See this for details。
理论上,你可以在这个位字段和一个: 3
位之间创建一个联合,但这种实践的结果将不可预测,也不能很好地定义。
最好的解决方案是摆脱位字段并用确定性的100%便携式解决方案替换它:
typedef struct
{
uint8_t flags;
} data_t
#define FLAG_A 0x01u
#define FLAG_B 0x02u
#define FLAG_C 0x04u
#define FLAG_ALL (FLAG_A | FLAG_B | FLAG_C)
data_t data = { .flags = FLAG_A | FLAG_B | FLAG_C};
if(data.flags & FLAG_ALL)
...
答案 1 :(得分:2)
比特字段使用完全不可移植。您无法确定 每个字段在底层结构中的位置。 Per 6.7.2.1结构和联合说明符,the C Standard的第11段:
实现可以分配任何可寻址的存储单元 足以容纳一个位域。如果剩余足够的空间,那就是一个位域 紧接着结构中的另一个位字段应该被打包 进入同一单元的相邻位。如果剩余空间不足, 是否将不适合的位域放入下一个单元或 重叠相邻单元是实现定义的。 的顺序 单位内的位域分配(高位到低位或 低阶到高阶)是实现定义的。对齐 可寻址存储单元未指定。