有人提醒我注意以下程序:
#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.z为int.
6.7.2.1 第 10 段(强调是后加的):
\n\n\n\n\n实现可以分配足够大的任何可寻址存储单元来容纳位\n字段。如果剩余足够的空间,则 \n 结构中紧随另一个位字段的位字段应打包到同一单元的相邻位中。如果insuf\xef\xac\x81cient 空间剩余,\n 不适合的位域是否被放入下一个单元或与相邻单元重叠是\n 实现de\xef\xac\x81ned。单元内位\xef\xac\x81字段的分配顺序(高位到\n低位或低位到高位)是由实现决定的。可寻址存储单元的对齐\n 未指定\xef\xac\x81ed。
\n
因此,在回答您的问题(我不再认为是重复的)时,如果编译器允许将实现定义的类型用作位字段的类型,则似乎不需要为此分配足够的大小type,大小仅足以容纳实际位字段。当然,它似乎也有权为位域分配 4 KB。
\n| 归档时间: |
|
| 查看次数: |
278 次 |
| 最近记录: |