位域的可用性

Usability of bitfields

有很多建议说不要使用位域,而是手动进行位运算(例如,When to use bit-fields in C?),因为位域布局是实现定义的。

这实际上是个问题吗?例如,我注意到 SysV ABI for x86-64 定义了位域的布局方式,因此我认为即使混合由不同编译器生成的目标代码,在此平台上使用位域也不会有问题。

位域是否也在其他平台上进行了类似的标准化? (我主要对 Linux (SysV ABI)、MacOs 和 CygWin 感兴趣。)

在编程中通常没有一个简单的答案。它总是取决于许多情况。

IMO,答案取决于您打算使用它们做什么。

如果您想要具有可预测行为和可读代码的特定位大小整数 - 是

struct 
{
    unsigned cnt: 3;
}three_bit_counter;

three_bit_counter.cnt++;

如果你编程 uC - 是

如果你想在位域结构中使用相同的代码和 "pack" 数据 - 不行。

这只是一些例子。当编码很好时考虑许多选项而不是 "gurus" 意见建议。

struct 
{
    unsigned cnt: 3;
    unsigned cnt1: 4;
}three_bit_counter;

unsigned cnt;


void inccnt(void)
{
    three_bit_counter.cnt++;

}
void inccnt1(void)
{
    three_bit_counter.cnt1++;

}

void inccntmask(void)
{
    unsigned tmp = cnt & 7;
    tmp++;
    tmp &= 7;

    cnt &= ~7;
    cnt |= tmp;

}

void inccnt1mask(void)
{
    unsigned tmp = cnt & (0b1111 << 3) >> 3;

    cnt &= ~(0b1111 << 3);
    tmp++;
    tmp &= 0b1111;
    cnt |= tmp << 3;

}

[...] bitfield layouts are implementation-defined.

有些方面是实现定义的。其他未指定,例如为位域保留的可寻址存储单元的大小。

Is this practically a problem?

这取决于您要做什么。许多更广泛地适用于结构类型的相同问题在微观世界中适用于位域。其中,

  • 与通常的结构一样,包含位域的结构将被任何给定的实现一致地解释,但是
  • 与通常的结构一样,包含位域的结构可能会被不同的实现解释不同——可能只影响位域成员。
  • 与结构成员布局一样,实现在选择位域布局方面的自由度比一些程序员想象的要高。

I've noticed the SysV ABI for x86-64, for example, defines how bitfields should be laid out, so I suppose using bitfields on this platform shouldn't be problematic even if I mix object code generated by different compilers.

在混合可依赖于生成和使用相同位域布局的代码时,使用位域不会出现互操作性问题。

使用位域不会为代码带来可移植性问题,避免依赖于位域布局的细节。

这些问题相互矛盾,因为互操作性需要一致的布局,但依赖布局细节会产生可移植性问题。

Are bitfields similarly standardized on other platforms too? (I'm mainly interested in Linux (SysV ABI), MacOs, and CygWin.)

一般来说,对于托管实现(包括您的所有示例),将有一个定义位域布局的平台 ABI,用于平台内的软件互操作性。 ABI 与独立实现并不特别相关,但许多(如果不是全部)此类实现确实指定了位域布局的完整细节。如果您关心的是您是否可以 link 使用针对同一平台使用不同 C 实现编译的位域代码并获得正确工作的程序,那么答案几乎肯定是 "yes".