2

我试图找到一个我不应该写的理由

struct bitfield {
  signed foo:4;
  unsigned bar:2;
};

而不是详细指定

struct bitfield {
  signed int foo:4;   
  unsigned int bar:2; 
};

由于位域的每个成员的大小都在冒号后明确指定,是否有任何缺点?

我是否使用char, short, long,有关系long long吗?指定的位域位数是否必须总是小于声明类型的宽度?


发现了一些相关的问题:

答案范围从

  • 不要使用除 (signed/unsigned) 之外的任何其他类型int_Bool
  • _Bool, signed int,unsigned int或其他一些实现定义的类型。(C99 6.2.7.1 (4) )

在这种情况下:这种不特定的其他一些实现定义的类型可能是什么样的,我在这个地方的选择可能会产生哪些其他缺点?

4

2 回答 2

3

“有时”和“是”

C99 要求宽度表达式“不超过指定类型的对象中的位数”,因此如果使用的类型太小,代码要么无法编译,要么至少不可移植。见§6.7.2.1 (3)。

关于更新的第三个问题和一般,“究竟是什么后果?” 问题,可能受到影响的事情是:可移植性、对齐和填充。该标准仅对第一个给出了明确的规范。如果没有位域,通常可以根据预测编译器会做什么来生成最佳对齐值来安排对齐和填充。虽然不能保证,但似乎在某些环境中使用类似short的东西会因为减少对齐和填充而节省内存。

实现精确布局和可移植性偶尔冲突目标的一种可能方法是声明没有位字段的内存数据结构,可能使用<stdint.h>类型。然后,如果您想使用位域来解码某些内容,请将内存中的源对象分配给一个临时变量,该变量是位域和位特定类型的联合,或者通过强制转换来故意违反类型双关规则指针。(Linux 无处不在。)

更好的方法可能是避免位域。

于 2012-04-22T19:43:02.227 回答
2

在您的代码的两个版本中,宽度都是明确的;这是有符号和无符号的宽度intsigned只是 的别名int, 也是signed int。同样,unsigned是 的别名unsigned int。Lone signedand unsignedare 不是修饰符,而是本身的类型名称。

于 2012-04-22T19:24:20.550 回答