R..*_*R.. 16 c language-lawyer bit-fields c11
我在C标准中找不到指定的任何地方.例如,在
struct { signed int x:1; } foo;
Run Code Online (Sandbox Code Playgroud)
是foo.x
一个类型的左值int
,还是其他什么?int
因为你不能在其中存储任何类型的值int
,只有0或-1,但它找不到任何类型的语言,这似乎是不自然的.当然,在大多数表达式中使用它,int
无论如何它都会被提升,但是实际的类型在C11中有所不同_Generic
,而且我在标准中找不到任何关于位域如何与之交互的语言_Generic
.
正如Jonathan所引用的那样,p5清楚地说明了比特字段的类型.
您还应该记住的是,6.3.1.1中的位域算术转换有一个特殊规则,基本上说明如果一个int
可以表示所有值,那么位字段将转换为int
大多数表达式.
a中的类型_Generic
应该是声明的类型(以符号小故障为模),因为似乎是算术转换不适用的共识.所以
_Generic((X), int: toto, unsigned: tutu)
_Generic(+(X), int: toto, unsigned: tutu)
Run Code Online (Sandbox Code Playgroud)
如果X
是无符号位域,其宽度具有所有值,则可以给出不同的结果int
.
鉴于您包含了signed
限定符,那么可以存储在 1 位位字段中的唯一值确实是 -1 和 0。如果您省略了限定符,则将由实现定义“普通”位int
字段是否为已签名或未签名。当然,如果您指定了unsigned int
,则值将为 0 和 +1。
该标准的相关章节是:
\n\n\n\n\n\xc2\xa76.7.2.1 结构和联合说明符
\n\n\xc2\xb64 指定位域宽度的表达式应为具有非负值的整数常量表达式,该值不超过由冒号和表达式指定的类型的对象的宽度省略。122)如果值为零,则声明不应有声明符。
\n\n\xc2\xb65 位字段的类型应为
\n\n_Bool
、signed\n int
、unsigned int
或某些其他实现定义的类型的限定或非限定版本。是否允许原子类型是由实现定义的。\xc2\xb610 位字段被解释为具有由指定位数组成的有符号或无符号整数类型。125)如果值 0 或 1 存储到类型 的非零宽度位字段中
\n\n_Bool
,则该位字段的值应等于存储的值;\n 位字段_Bool
具有 a 的语义_Bool
。122)虽然对象中的位数
\n\n_Bool
至少为CHAR_BIT
,但 a 的宽度(符号和值位数)_Bool
可能仅为 1 位。125)如上面 6.7.2 中指定的,如果使用的实际类型说明符是
\nint
或定义为 的 typedef-nameint
,则无论位域是有符号还是无符号,它都是实现定义的。
脚注125指出:
\n\n\n\n\xc2\xa76.7.2 类型说明符
\n\n\xc2\xb65 每个逗号分隔的多重集都指定相同的类型,除了位域之外,\n 说明符是否
\nint
指定与\n 相同的类型signed int
还是与 相同的类型是实现定义的unsigned int
。