位字段可移植性

时间:2014-08-17 02:04:32

标签: c portability bit-fields

我读here位字段不可移植。这是否意味着下面的代码定义位字段(代码来自here)无法在某些机器上编译?

如果是这样,为什么呢?

#include <stdio.h>
#include <string.h>

/* define simple structure */
struct
{
  unsigned int widthValidated;
  unsigned int heightValidated;
} status1;

/* define a structure with bit fields */
struct
{
  unsigned int widthValidated : 1;
  unsigned int heightValidated : 1;
} status2;

int main( )
{
   printf( "Memory size occupied by status1 : %d\n", sizeof(status1));
   printf( "Memory size occupied by status2 : %d\n", sizeof(status2));

   return 0;
}

3 个答案:

答案 0 :(得分:20)

比特字段是可移植的,因为它们是标准(C11部分6.7.2.1)中指定的C语言的一部分。任何无法识别使用位域的代码的编译器都不符合标准。对你的例子也没有什么可疑的,因为它只是有位域存在。

它们可能意味着字段本身可能在位置和顺序上无法预测地包装(标准,前面的参考文献第11段允许)。这意味着一个结构,例如,大小为4,12,13和3的四个位域不一定占用32位,并且它们不一定按照该顺序放在结构中;编译器可以将它们放在喜欢的位置。这意味着不能将结构视为基础二进制对象的实际组件表示。

相比之下,手动应用于整数的位掩码恰好存在于放置它们的位置。如果你定义掩盖了无符号整数的前4位,后12位等的掩码,那么&#34;字段&#34;将实际应用于位,按顺序和位置(假设您知道字节顺序,无论如何)。这使得表示编译器无关。

即。它们是便携式的,但它们所做的可能不一定是一个人真正想要操纵个别位的东西。

答案 1 :(得分:9)

位字段是标准语言功能。他们将在所有C编译器中编译。从这个意义上说,它们是便携式的。您的代码格式正确,并且将在所有C编译器中编译。

&#34;比特字段等语句不可移植&#34;通常意味着存储器中位域的物理布局可能因实现而不同(即从一个编译器到另一个编译器)。如果在不同的实现上编译,您可能从程序中获得不同的输出。但只有在代码依赖于具有位字段的对象的内存布局时(例如,如果您测量它们的大小,就像在程序中一样),程序行为的差异才会发生。

换句话说,&#34;位字段不可移植&#34;与int类型&#34;不可移植&#34;类似的几乎是一样的。仅仅因为它在不同平台上可以有不同的大小,或者在其内部表示中使用不同的字节序。

答案 2 :(得分:3)

{C}要求int至少为16位。因此,如果您希望在最大可移植代码中使用位字段,则不能使用占位超过16位的位字段。 / p>

C.11§6.7.2.1¶5:

  

位字段的类型应为_Boolsigned intunsigned int或其他实现定义类型的合格或非限定版本。

C.11§5.4.2.1¶1:

  

- 类型int的对象的最大值
  INT_MAX +32767 // 2 15 - 1
   - 类型unsigned int的对象的最大值
  UINT_MAX 65535 // 2 16 - 1