C 整数宽度在位字段声明中是否相关?

C 整数宽度在位字段声明中是否相关?,c,integer,bit-fields,C,Integer,Bit Fields,我试图找到一个不应该写作的理由 struct bitfield { signed foo:4; unsigned bar:2; }; 而不是详细地指定 struct bitfield { signed int foo:4; unsigned int bar:2; }; 由于位字段的每个成员的大小都是在冒号之后显式指定的,因此会有任何缺点吗 如果我使用char,short,long,long,有关系吗?指定的位字段位数必须始终小于声明类型的宽度吗 发现一些相关问题:

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

struct bitfield {
  signed foo:4;
  unsigned bar:2;
};
而不是详细地指定

struct bitfield {
  signed int foo:4;   
  unsigned int bar:2; 
};
由于位字段的每个成员的大小都是在冒号之后显式指定的,因此会有任何缺点吗

如果我使用
char
short
long
long
,有关系吗?指定的位字段位数必须始终小于声明类型的宽度吗


发现一些相关问题:

答案从

  • 除了(有符号/无符号)
    int
    \u Bool
  • \u Bool
    有符号整数
    无符号整数
    ,或其他实现定义的类型。(C996.2.7.1(4))

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

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

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

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

实现精确布局和可移植性这两个偶尔冲突的目标的一种可能方法是声明内存中没有位字段的数据结构,可能使用
类型。然后,如果要使用位字段来解码某些内容,请将内存中的源对象指定给一个临时变量,该临时变量是位字段和位特定类型的并集,或者通过强制转换指针故意违反类型双关规则。(Linux到处都是这样做的。)


一个更好的方法可能是避免使用位字段。

的确如此,但我要问的是,为什么我会选择
short
而不是
int
或类似的。不,我认为这里的
签名
不是多余的。
int
位字段可以具有无符号类型的语义。J.3.9将此标记为实现定义的行为。事实上,我忘记了那个丑陋的特例。很遗憾,我不是回答这个问题的合适人选,但这个问题让我感到好奇,我浏览了一下web。C90、C99和C++都对允许的类型有不同的定义,更糟糕的是,似乎有些编译器使用类型来确定结构的最小大小(即,长FoO:1可能导致更大的结构,然后INTFO:1)对主题有有趣的信息。