我有一个包含位字段的结构:
struct Foo {
unsigned a : 16, b : 16;
};
我想知道我是否可以在它的位域上使用聚合初始化。例如:
struct Foo bar = {13, 42};
我注意到这个does work in gcc 5.1和Visual Studio 2015.我只是想证明这是C和C ++的标准批准初始化。
答案 0 :(得分:8)
来自C ++ 14 [dcl.init.aggr]
我们有
聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚拟功能(10.3)。
因此Foo
是聚合初始化的合格资格。然后我们有
当初始化列表初始化聚合时,如8.5.4中所述,初始化列表的元素被视为聚合成员的初始化者,增加下标或成员顺序。[...] < / p>
和
出于聚合初始化的目的,静态数据成员和匿名位字段不被视为类的成员。
因此,在您的情况下,它们将被初始化,因为它们不是匿名的,它们将按照它们在struct
中出现的顺序进行初始化。
从C11 6.2.5(21)我们有
算术类型和指针类型统称为标量类型。数组和结构类型统称为聚合类型。 46 )
所以在C中我们仍在处理聚合。然后在6.7.9(9)中我们有
除非另有明确说明,否则为了本子条款的目的,结构和联合类型的对象的未命名成员不参与初始化。即使在初始化之后,未命名的结构对象成员也具有不确定的值。
和6.7.9(17)
每个大括号括起的初始化列表都有一个关联的当前对象。什么时候没有 如果存在名称,则根据当前对象的类型按顺序初始化当前对象的子对象:增加下标顺序的数组元素,声明顺序中的结构成员,以及union的第一个命名成员。 148 )相反,指定使得以下初始化器开始初始化由指示符描述的子对象。然后初始化按顺序继续向前,从指定者描述的下一个子对象开始。 149 )
因此,我们的行为与C ++中的行为相同,其中匿名位字段未初始化,但由于它们已命名,因此将按照它们在struct
中显示的顺序进行初始化。