关于可移植性:为什么C ++位字段以及如何不可移植?

Why and how are C++ bitfields non-portable?

关于位域的各种问题,我遇到过许多评论,这些论断断言了位域不可移植,但是我从来没有找到确切解释其原因的资料。

从表面上看,我应该假设所有位域都只能编译为相同移位码的变体,但是显然,它必须比它还要多,否则它们不会有如此强烈的反感。

所以我的问题是什么使位域不可移植?


位字段不可移植,就如同整数不可移植一样。您可以使用整数来编写可移植程序,但是不能期望将int的二进制表示形式原样发送到远程计算机,并希望它正确地解释数据。

这是因为1.处理器的字长有所不同,因此整数类型的大小也有所不同(1.1字节长度也可能有所不同,但这是当今嵌入式系统以外的罕见情况)。并且因为2.字节字节顺序在处理器之间不同。

这些问题很容易克服。本地字节序可以很容易地转换为约定的字节序(大字节序是网络通信的事实上的标准),并且可以在编译时检查大小,并且如今可以使用固定长度的整数类型。因此,只要照顾到这些细节,就可以使用整数在网络上进行通信。

位字段基于常规整数类型构建,因此它们在字节序和整数大小方面存在相同的问题。但是它们具有更多的实现指定行为。

  • Everything about the actual allocation details of bit fields within the class object

    • For example, on some platforms, bit fields don't straddle bytes, on others they do
    • Also, on some platforms, bit fields are packed left-to-right, on others right-to-left
  • Whether char, short, int, long, and long long bit fields are signed or unsigned (when not declared so explicitly).

与字节顺序不同,将"有关实际分配详细信息的所有内容"转换为规范形式并非易事。

同样,虽然字节序是cpu体系结构特定的,但是位字段详细信息是特定于编译器实现者的。因此,位域即使在同一计算机内的不同进程之间也无法移植以进行通信,除非我们可以保证它们是使用相同(或二进制兼容)编译器进行编译的。

TL; DR位字段不是计算机之间进行通信的可移植方式。整数都不是,但是它们的不可移植性很容易解决。


在未指定位顺序的意义上,位字段不可移植。因此,使用一个编译器在索引0处的位很可能是另一个编译器的最后一位。

这样可以防止在应用程序中使用位字段,例如在内存映射的硬件寄存器中切换位。

但是,您会看到硬件供应商在它们发布的代码中使用了位域(例如,像微芯片)。通常,这是因为他们也随之一起发布了编译器或针对了单个编译器。以微芯片为例,其源代码的许可要求您使用自己的编译器(用于8位低端设备)

@Pharap指向的链接包含与此未指定的排序有关的(c ++ 14)规范的摘录:is-there-a-portable-alternative-to-c-bitfields