位域的可用性

时间:2019-05-04 13:09:36

标签: c portability abi

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

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

其他平台上的位域也同样标准化吗? (我主要对Linux(SysV ABI),MacO和CygWin感兴趣。)

2 个答案:

答案 0 :(得分:1)

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

IMO,答案取决于您打算将其用于什么目的。

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

struct 
{
    unsigned cnt: 3;
}three_bit_counter;

three_bit_counter.cnt++;

如果您编程uC-是

如果要使用相同的代码并将数据“打包”到位域结构中-不。

这只是一些示例。当编码很好时,要考虑很多选项,而不要被“专家”的意见所建议。

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;

}

答案 1 :(得分:1)

  

[...]位域布局是实现定义的。

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

  

这实际上是个问题吗?

这取决于您要执行的操作。许多更广泛适用于结构类型的相同问题在微观上适用于位域。其中

  • 通常,与结构类似,包含位域的结构将由任何给定的实现一致地解释,但是
  • 通常,与结构类似,包含位域的结构可能会通过不同的实现方式进行不同的解释-可能仅影响位域成员。
  • 像结构成员的布局一样,实现方式比某些程序员认为的要有更多的自由选择位域布局。
  

我注意到x86-64的SysV ABI,   例如,定义位域的布局方式,所以我想   即使在我的平台上使用位域也应该没问题   混合由不同编译器生成的目标代码。

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

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

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

  

其他平台上的位域也同样标准化吗? (我是   主要对Linux(SysV ABI),MacO和CygWin感兴趣。)

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