位域声明中的整数宽度是否相关?

我试图找到一个我不应该写的原因

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

而不是详细说明

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

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

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


发现了一些相关问题:

  • 除int之外的其他类型的位域?
  • 在位域内声明不同数据类型有什么用?

答案范围从

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

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

“有时”,“是”

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

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

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

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

在两个版本的代码中,宽度都是明确的; 它是signed和unsigned int的宽度。 signed只是int的别名,因此是signed int 。 同样, unsignedunsigned int的别名。 单独signedunsigned不是修饰符,而是类型名称。