【发布时间】:2019-11-19 07:33:00
【问题描述】:
我以前在 C 方面有过一些经验,但是我以前从未见过位域功能。我知道可以使用位掩码来隔离数据结构中的某些位,但是为什么还要使用位域呢?
例如,假设我们要隔离的位是前 3 个最低有效位。然后我们可以写:
/* our bitmasks */
#define FIELD_A (1 << 0)
#define FIELD_B (1 << 1)
#define FIELD_C (1 << 2)
int main(void)
{
/* the data structure that contains our three fields */
uint8_t flags;
/* accessing field A (as a boolean) */
int bool_a = !!(flags & FIELD_A);
/* accessing field B (as a boolean) */
int bool_b = !!(flags & FIELD_B);
/* accessing field C (as a boolean) */
int bool_c = !!(flags & FIELD_C);
return 0;
}
为什么我们会选择这样写:
static struct fields {
int field_a : 1;
int field_b : 1;
int field_c : 1;
};
int main(void)
{
/* the data structure that contains our three fields */
struct fields flags;
/* accessing field A */
int bit_a = flags.a;
/* accessing field B */
int bit_b = flags.b;
/* accessing field C */
int bit_c = flags.c;
return 0;
}
【问题讨论】:
-
位掩码方法更加便携和健壮。坚持下去。尽管位域看起来很方便。除非你不关心位的布局。
-
您的第一个示例不正确。您希望按用于在
#define中移动的数字进行移动,而不是按FIELD_X本身。 -
@P__J__ 对于任何“非便携式”声明都是如此。但是在位域的情况下,甚至无法从代码中清楚地看出哪个位是 LSB,哪个是 MSB。也不清楚整个位域的宽度是多少。还有一些其他有趣的事情,只有通过实验或深入挖掘编译器文档才能发现。
-
@P__J__ 编码时,迂腐获得第一。
-
int field_a : 1;实际上是不正确的:如果设置了单个位,int位域可能会被读取为-1而不是1。你应该写unsigned int field_a : 1;
标签: c bit-manipulation bit-fields bitmask