是否允许比特字段的聚合初始化?

我有一个包含位字段的结构:

struct Foo { unsigned a : 16, b : 16; }; 

我想知道我是否可以在它的位字段上使用聚合初始化。 例如:

 struct Foo bar = {13, 42}; 

我注意到这在gcc 5.1和Visual Studio 2015中都有效。我只想certificate这是C和C ++的标准批准初始化。

从C ++ 14 [dcl.init.aggr]我们有

聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3) )。

所以Foo是聚合初始化的聚合资格。 然后我们有

当聚合由初始化列表初始化时,如8.5.4中所规定,初始化列表的元素被视为聚合成员的初始化者,增加下标或成员顺序。[…]

出于聚合初始化的目的,静态数据成员和匿名位字段不被视为类的成员。

因此,在您的情况下,它们将被初始化,因为它们不是匿名的,它们将按它们在struct出现的顺序进行初始化。

从C11 6.2.5(21)我们得到

算术类型和指针类型统称为标量类型。 数组和结构类型统称为聚合类型。 46

所以在C中我们仍在处理聚合。 然后在6.7.9(9)我们有

除非另有明确说明,否则为了本子条款的目的,结构和联合类型的对象的未命名成员不参与初始化。 即使在初始化之后,未命名的结构对象成员也具有不确定的值。

和6.7.9(17)

每个大括号括起的初始化列表都有一个关联的当前对象。 当没有指定时,根据当前对象的类型按顺序初始化当前对象的子对象:增加下标顺序的数组元素,声明顺序中的结构成员,以及union的第一个命名成员。 148 )相反,指定使得以下初始化器开始由指示符描述的子对象的初始化。 然后,初始化按顺序继续向前,从指定者描述的下一个子对象开始。 149

因此,我们具有与C ++相同的行为,其中匿名位字段未初始化但由于它们被命名,因此它们将按它们在struct出现的顺序进行初始化。