3

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

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

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

struct Foo bar = {13, 42};

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

4

1 回答 1

8

从 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.

于 2016-01-18T14:24:03.207 回答