为什么以及如何使C ++位域不可移植?

时间:2016-07-05 07:19:41

标签: c++ portability bit-fields

关于位域声称位域不可移植的各种问题,我遇到过很多评论,但我从来没能找到解释原因的来源。

从表面上看,我会假设所有的位域只是编译成相同位移码的变化,但显然必须有更多的位置,或者不会有这样的强烈不喜欢它们。

所以我的问题是是什么让bitfields不可移植?

2 个答案:

答案 0 :(得分:11)

比特字段是非便携式的,因为整数是不可移植的。您可以使用整数来编写可移植程序,但是您不能期望将int的二进制表示形式发送到远程计算机并期望它正确地解释数据。

这是因为1.处理器的字长不同,因此,整数类型的大小不同(1.1字节长度也可能不同,但现在这种情况在嵌入式系统之外很少见)。因为2.字节字节顺序因处理器而异。

这些问题很容易克服。原生字节顺序可以很容易地转换为商定的字节顺序(big endian是网络通信的事实标准),并且可以在编译时检查大小,并且这些天可以获得固定长度的整数类型。因此,只要这些细节得到处理,整数就可以用于通过网络进行通信。

位字段构建在常规整数类型上,因此它们具有相同的字节顺序和整数大小的问题。但是他们有even more实现指定的行为。

  
      
  • 关于类对象中位域的实际分配细节的一切

         
        
    • 例如,在某些平台上,位字段不会跨越字节,而在其他平台上则
    •   
    • 此外,在某些平台上,位字段从左到右打包,其他位从右到左打包
    •   
  •   
  • 未明确签名或未签名的char,short,int,long和long长位字段是有符号还是无符号。

  •   

与endianness不同,将“关于实际分配细节的所有内容”转换为规范形式并非易事。

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

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

答案 1 :(得分:3)

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

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

但是,您会看到硬件供应商在他们发布的代码中使用位域(例如微芯片)。通常,这是因为它们还使用它释放编译器或以单个编译器为目标。例如,在微芯片的情况下,源代码的许可证要求您使用自己的编译器(对于8位低端设备)

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