繁体   English   中英

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

[英]Why and how are C++ bitfields non-portable?

我遇到了很多关于位域的各种问题的评论,断言位域是不可移植的,但我从来没有找到准确解释原因的来源。

从表面上看,我会假设所有位域只是编译为相同位移代码的变体,但显然它肯定不止于此,否则不会对它们产生如此强烈的反感。

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

位域是不可移植的,就像整数不可移植一样。 您可以使用整数来编写可移植程序,但您不能期望将int的二进制表示按原样发送到远程机器并期望它正确解释数据。

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

这些问题很容易克服。 本机字节序可以很容易地转换为商定的字节序(大字节序是网络通信的事实上的标准),并且可以在编译时检查大小,并且现在可以使用固定长度的整数类型。 因此,整数可用于跨网络通信,只要处理这些细节即可。

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

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

    • 例如,在某些平台上,位域不跨字节,而在其他平台上则跨字节
    • 此外,在某些平台上,位字段从左到右打包,在其他平台上从右到左打包
  • char、short、int、long 和 long long 位字段是有符号还是无符号(如果没有明确声明)。

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

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


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

位域是不可移植的,因为位的顺序是未指定的。 因此,一个编译器的索引 0 处的位很可能是另一个编译器的最后一位。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM