C 位域的可用性

C 位域的可用性,c,portability,abi,C,Portability,Abi,有很多建议建议不要使用位字段,而是手动执行位运算(例如),因为位字段布局是由实现定义的 这实际上是个问题吗?我注意到,例如,定义了位字段的布局方式,所以我认为在这个平台上使用位字段应该不会有问题,即使我混合了由不同编译器生成的目标代码 其他平台上的位字段是否也同样标准化?(我主要对Linux(SysV ABI)、MacOs和CygWin感兴趣。)通常在编程中没有一个简单的答案。这取决于很多情况 在我看来,答案取决于你打算用它们做什么 如果您想要具有可预测行为和可读代码的特定位大小整数-是 str

有很多建议建议不要使用位字段,而是手动执行位运算(例如),因为位字段布局是由实现定义的

这实际上是个问题吗?我注意到,例如,定义了位字段的布局方式,所以我认为在这个平台上使用位字段应该不会有问题,即使我混合了由不同编译器生成的目标代码


其他平台上的位字段是否也同样标准化?(我主要对Linux(SysV ABI)、MacOs和CygWin感兴趣。)

通常在编程中没有一个简单的答案。这取决于很多情况

在我看来,答案取决于你打算用它们做什么

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

struct 
{
    unsigned cnt: 3;
}three_bit_counter;

three_bit_counter.cnt++;
如果你为uC编程-是

如果您想使用相同的代码并将数据“打包”到位字段结构中,则-否

这只是一些例子。当编码是好的,考虑许多选项,而不是“Gururs”的意见。

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;

}
struct
{
未签名cnt:3;
未签名cnt1:4;
}三位计数器;
无符号碳纳米管;
无效增量(无效)
{
三位计数器.cnt++;
}
无效inccnt1(无效)
{
三位计数器.cnt1++;
}
void inccntmask(void)
{
无符号tmp=cnt&7;
tmp++;
tmp&=7;
cnt&=~7;
cnt |=tmp;
}
无效incnt1mask(void)
{
无符号tmp=cnt&(0b1111>3;
cnt&=~(0b1111)
[…]位字段布局由实现定义

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

这实际上是个问题吗

这取决于你想做什么。许多同样的问题更广泛地适用于结构类型,也适用于微观世界中的比特域。其中

  • 与通常的结构一样,包含位字段的结构将由任何给定的实现一致地解释,但是
  • 与通常的结构一样,包含位字段的结构可能会被不同的实现以不同的方式解释——可能只影响位字段成员
  • 与结构成员布局一样,实现比一些程序员所设想的更自由地选择位字段布局
我注意到x86-64的SysV ABI, 例如,定义了位字段应该如何布局,所以我认为 在这个平台上使用位字段应该不会有问题,即使我 混合由不同编译器生成的目标代码

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

使用位字段不会对避免依赖位字段布局细节的代码造成可移植性问题

这些都是相互冲突的问题,因为互操作性需要一致的布局,但依赖布局细节会造成可移植性问题

其他平台上的位域是否也同样标准化了 主要对Linux(SysV ABI)、MacOs和CygWin感兴趣。)


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

注意x86和x86-64上的Linux遵循SysV ABI。@Cacahuetferito
是有意义的,因为没有人使用它们
非常强烈但毫无意义的观点。只需看看PIC或AVR XMEGA库大多数o/s(平台)拥有ABI,平台上的编译器将遵循ABI。但是,如果您在不同平台之间传输二进制数据,则无法保证可以在一个平台上处理的位字段可以在另一个平台上正常解释。好吧,没有使用位字段的系统调用。@Rob我认为问题不在这里基于这样的观点:做(至少)最流行的平台标准化位域,其中C标准定义了实现?我相信你的话,这里有一些有趣的用例。我没有见过它们,但我不负责与硬件寄存器等的接口。在工作空间之外,我认为它们没有什么兴趣。一般来说,你最好使用b它掩盖了问题的第二部分:标准化是的,最后一句。谢谢。(我想使用位字段的主要原因是在面向用户的配置结构中(
struct ns_fn_cfg{unsigned flag1:1,flag2:1,flag3;}
)它们比要求用户或某些
NS_FN_CFG_FLAG1 | NS_FN_CFG_FLAG2 | NS_FN_CFG_FLAG3
更好地使用,而且它们的调用方代码根也比我使用许多非位域的
\u Bool
字段时得到的更好。)