Vek*_*eky 10 c struct initialization ansi bit-fields
当你写作
struct {
unsigned a:3, b:2;
} x = {10, 11};
Run Code Online (Sandbox Code Playgroud)
被x.b保证是3由ANSI C(C89)?我已阅读并重新阅读标准,但似乎无法找到确切的情况.
例如,"无法用结果无符号整数类型表示的结果以模数的形式减少,该数字大于可由结果无符号整数类型表示的最大值." 谈论计算,而不是初始化.而且,位字段实际上不是一种类型.
此外,(当谈到无符号t:4时)"包含[0,15]范围内的值",但这并不一定意味着初始化器必须以模16减少以映射到[0,15].
结构初始化真的是详细描述,但我似乎无法找到确切的行为.(当然编译器就是这样做的.而且IBM文档说"当你将一个超出范围的值分配给一个位字段时,保留低位模式并分配适当的位.",但是我想要要知道ANSI C是否标准化了.
"ANSI C"/ C89已经淘汰了25年.因此,我的回答引用了当前的C标准ISO 9899:2011,也称为C11.
几乎所有与C标准中的位字段相关的内容都定义不明确.通常,您不会发现任何明确解决位字段行为的内容,但它们的行为是隐式指定的,"在行之间".这就是为什么你应该避免使用位字段.
但是,我认为这个特定情况是明确定义的:它应该像任何其他整数初始化一样工作.
您提到的详细结构初始化规则(6.7.9)显示11了初始化列表中的文字与变量的关系b.没什么奇怪的.然后适用的是"简单的任务",就像你写的一样x.b = 11;.
在C中进行任何类型的赋值或初始化时,右操作数将转换为左操作数的类型.这由C11 6.5.16规定:
在简单赋值(=)中,右操作数的值将转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值.
在您的情况下,int11类型的文字转换为unsigned int:2的位字段.
因此,您要查找的规则应在涉及转换的章节中找到(C11 6.3).适用的是您在问题中引用的内容,C11 6.3.1.3:
...如果新类型是无符号的,则通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内.
一个的最大值无符号整型:2是3.一个小于最大值更多的是3 + 1 = 4.编译器应该重复从值11中减去它:
11 - (3+1) = 7 does not fit, subtract once more:
7 - (3+1) = 3 does fit, store value 3
Run Code Online (Sandbox Code Playgroud)
但是当然,这与将十进制值11的2个最低有效位存储在位字段中是完全相同的.
WRT“讲的是计算,而不是初始化”,C89 标准明确地将赋值和转换规则应用于初始化。它还说:
位字段被解释为由指定位数组成的整数类型。
鉴于这些,虽然编译器警告显然是合理的,但标准似乎保证丢弃高位。