繁体   English   中英

初始化位域

[英]Initializing bit-fields

当你写

struct {
    unsigned a:3, b:2;
} x = {10, 11};

ANSI C(C89)确保xb3 我已经阅读并重新阅读了该标准,但似乎找不到确切的情况。

例如,“无法用所得的无符号整数类型表示的结果以比所得的无符号整数类型可以表示的最大值大一的模数减少。” 谈到计算,而不是初始化。 而且,位域并不是真正的类型。

另外,(当谈到无符号的t:4时)“包含[0,15]范围内的值”,但这并不一定意味着必须将初始值设定为16 ,以映射到[0,15]。

确实很详细地描述了结构初始化,但是我似乎确实找不到确切的行为。 (当然,编译器确实会这样做。IBM文档说“当您将超出范围的值分配给位字段时,将保留低位位模式并分配了适当的位。”,但我想知道ANSI C是否将其标准化。

“ ANSI C” / C89已经过时25年了 因此,我的答案引用了当前的C标准ISO 9899:2011,也称为C11。


几乎所有与C标准中的位域有关的东西都定义不清。 通常,找不到任何明确解决位字段行为的东西,而是隐式地在“行之间”指定它们的行为。 这就是为什么您应该避免使用位字段的原因。

但是,我相信这种特定情况是明确定义的:它应该像其他整数初始化一样工作。

您提到的详细的struct初始化规则(6.7.9)显示了初始化程序列表中的文字11与变量b是如何相关的。 没什么奇怪的。 然后适用的是“简单赋值”,就像您写xb = 11;一样会发生xb = 11;

在C中进行任何类型的赋值或初始化时,右操作数将转换为左操作数的类型。 这由C11 6.5.16指定:

在简单赋值(=)中,将右操作数的值转换为赋值表达式的类型,并替换存储在由左操作数指定的对象中的值。

在您的情况下,类型为int的文字11将转换为unsigned int:2的位字段。

因此,您要寻找的规则应该在处理转换(C11 6.3)的章节中找到。 适用的是您在问题C11 6.3.1.3中已经引用的内容:

...如果新类型是无符号的,则通过重复添加或减去比新类型可表示的最大值多一个值来转换该值,直到该值在新类型的范围内。

无符号int:2的最大值为3。大于最大值的1为3 + 1 = 4。 编译器应反复从值11中减去此值:

11 - (3+1) = 7    does not fit, subtract once more:
 7 - (3+1) = 3    does fit, store value 3

但是,当然,这与将十进制值11的2个最低有效位存储在位字段中是完全一样的。

WRT“谈论计算而不是初始化”,C89标准明确将赋值和转换规则应用于初始化。 它还说:

位字段被解释为由指定位数组成的整数类型。

鉴于这些情况,虽然显然会出现编译器警告,但似乎该标准保证了丢弃高阶位。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM