我有一个包含位字段的结构:
struct Foo {
unsigned a : 16, b : 16;
};
我想知道我是否可以在它的位域上使用聚合初始化。例如:
struct Foo bar = {13, 42};
我注意到这在 gcc 5.1和 Visual Studio 2015 中确实有效。我只是想证明这是标准批准的 C 和 C++ 初始化。
我有一个包含位字段的结构:
struct Foo {
unsigned a : 16, b : 16;
};
我想知道我是否可以在它的位域上使用聚合初始化。例如:
struct Foo bar = {13, 42};
我注意到这在 gcc 5.1和 Visual Studio 2015 中确实有效。我只是想证明这是标准批准的 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)
每个大括号括起来的初始值设定项列表都有一个关联的当前对象。当没有指定时,当前对象的子对象根据当前对象的类型按顺序初始化:数组元素按递增下标顺序,结构成员按声明顺序,以及联合的第一个命名成员。148 ) 相反,指定使后面的初始化器开始初始化由指定器描述的子对象。然后初始化按顺序继续向前,从指示符描述的子对象之后的下一个子对象开始。149 )
因此,我们的行为与 C++ 中的行为相同,其中匿名位字段未初始化,但由于它们被命名,它们将按照它们出现在struct
.