那里有很多建议,建议不要使用位域,而是手动执行位算术(例如When to use bit-fields in C?),因为位域布局是实现定义的。
这实际上是一个问题吗?例如,我注意到SysV ABI for x86-64定义了位域的布局方式,因此我认为即使我混合了不同编译器生成的目标代码,在该平台上使用位域也不会出现问题。
其他平台上的位域也同样标准化吗? (我主要对Linux(SysV ABI),MacO和CygWin感兴趣。)
答案 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实现编译的使用位域的代码,并获得可以正常工作的程序,那么答案几乎肯定是“是”。