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

时间:2011-09-13 19:54:54

标签: 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));
}

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

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

我在C99标准中找到的相关条款是6.3.1.1中的第2条,对于不基于_Boolintsigned int的位域似乎没有任何说法或unsigned int。该子句的第二部分,“如果int可以表示原始类型的所有值,则该值将转换为int,......”,似乎仅适用于该子句的第一部分,不包括基于long long int的位域。

此外,6.7.2.1说:

  

位字段应具有合格或不合格的类型   _Bool的版本,signed int,unsigned int或其他   实现定义的类型。

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

我在StackOverflow上找到了this question,它指向“编译器可以创建他们自己的规则”方向,但我仍然错过了Clang和GCC都输入S10.z作为{ {1}}。

1 个答案:

答案 0 :(得分:3)

6.7.2.1第10段(强调增加):

  

一个实现可以分配任何足够大的可寻址存储单元来保存位 -   字段。如果剩余足够的空间,则紧跟在a中的另一个位字段之后的位字段   结构应打包到同一单元的相邻位。如果剩余的空间不足,   是否将不适合的位域放入下一个单元或重叠相邻单元   实施德网络定义。一个单元内的位域分配顺序(高位到   实现定义的是低阶或低阶到高阶。对齐   可寻址存储单元未指定。

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