当底层位域类型在C中不是int时,lvalue.bitfield的类型

Pas*_*uoq 5 c c99 bit-fields

有人提醒我注意以下程序:

#include <stdio.h>

struct X50 {
 long long int z:50;
} s50 = { 2 };

struct X10 {
 long long int z:10;
} s10 = { 2 };

int main() {
  printf("%zu %zu %zu\n",sizeof(long long int),sizeof(s10.z+1),sizeof(s50.z+1));
}
Run Code Online (Sandbox Code Playgroud)

表达式的类型sizeof(lv.z+1)是根据"通常的算术转换"计算的,几乎可以说左值的类型大小lv.z将反映在加法的类型上,只要它至少是这样int.

我没想到这种类型取决于位域的大小,但确实如此:GCC和Clang都打印8 4 8在我的计算机上.

我在C99标准中的相关条款是第2条中6.3.1.1,这似乎也不是那么说的位域没有任何根据_Bool,int,signed int,或unsigned int.该子句的第二部分,"如果一个int可以表示原始类型的所有值,该值转换为一个int,......",似乎只适用于该条款第一部分所述的条件,即不包括基于的位域long long int.

此外,6.7.2.1说:

位字段的类型应为_Bool,signed int,unsigned int或其他实现定义类型的限定或非限定版本.

是否因为long long int位域超出了标准的范围,编译器可以发明自己的规则,或者可以在C99的其他地方找到Clang和GCC行为的某种理由?

我发现这个问题在计算器上,这点在"编译器可以创造自己的规则"的方向发展,但仍然是我错过了锵和GCC会打字的理由S10.zint.

Chr*_*utz 3

6.7.2.1 第 10 段(强调是后加的):

\n\n
\n

实现可以分配足够大的任何可寻址存储单元来容纳位\n字段。如果剩余足够的空间,则 \n 结构中紧随另一个位字段的位字段应打包到同一单元的相邻位中。如果insuf\xef\xac\x81cient 空间剩余,\n 不适合的位域是否被放入下一个单元或与相邻单元重叠是\n 实现de\xef\xac\x81ned。单元内位\xef\xac\x81字段的分配顺序(高位到\n低位或低位到高位)是由实现决定的。可寻址存储单元的对齐\n 未指定\xef\xac\x81ed。

\n
\n\n

因此,在回答您的问题(我不再认为是重复的)时,如果编译器允许将实现定义的类型用作位字段的类型,则似乎不需要为此分配足够的大小type,大小仅足以容纳实际位字段。当然,它似乎也有权为位域分配 4 KB。

\n