初始化匿名联合的语法

时间:2013-06-28 15:45:40

标签: c++ unions

如果我在函数中声明匿名联合......

void f(int in) {
    union { int i; float f; };
    // …
}

...是否存在语法来初始化它(除了在另一个语句中分配给if?快速查看规范表明没有。显而易见的是不编译:

// Nope:
union { int i = in; float f; };
union { int i; float f; } = in;
union { int i; float f; } = {in};
union { int i; float f; }{in};
union { int i; float f; }(in);

2 个答案:

答案 0 :(得分:5)

这有效(至少在gcc 4.7.2中):

union { int i; float f; } x = {1};

请注意,类型(即union)是匿名的,但其实例称为x

你想要实现的目标(例如union { int i; float f; }{in};)不能编译,但假设它确实如此。然后,您将创建一个未命名类型的未命名对象(临时)。临时表将在表达式结束时销毁,因此,此语句将不起作用。那有什么意义呢?

答案 1 :(得分:2)

请参阅下面的更新 - 我不确定这是语言限制还是编译器限制。

在没有指定的初始值设定项的情况下(1999年添加到C中,据我所知目前在C ++中不存在),联合的初始值设定项只能为第一个命名成员指定一个值:

union { int i; float f; } obj = { 42 }; // sets obj.i to 42

C,从1999年标准开始,提供指定的初始值设定项,可以初始化您喜欢的任何命名成员:

union { int i; float f; } obj = { .f = 1.25 };

由于C ++没有这个功能,除非你碰巧想要初始化第一个命名成员,否则你几乎没有运气。

当然你可以使用作业:

union { int i; float f; } obj;
obj.f = 1.25;

我建议这是一个非常好的解决方法。你可以做你想做的;你不能用你想要的语法来做它。

在这种情况下,给union类型命名并不是特别有用,除非你在更广泛的范围内看到它并编写一个返回类型值的函数:

union u { int i; float f; };
u init_f(float f) { u result; result.f = f; return result; }

// later

u obj = init_f(1.25);

更新:

当我编写上述内容时,我不知道C ++中是否存在匿名联合。 C11允许匿名联合和结构,但仅作为封闭联合或结构的成员。 C ++ 11允许定义匿名联合对象,如本例中的标准:

void f() {
  union { int a; const char* p; };
  a = 1;
  p = "Jennifer";
}

g ++ 4.7.2似乎不允许初始化匿名联合对象。例如,这个:

int main() {
    union {
        int i;
        float f;
    } = { 42 };
}

导致g++ -std=c++11出现以下错误:

c.cpp: In function ‘int main()’:
c.cpp:5:5: error: expected ‘;’ after union definition
c.cpp:5:7: error: expected primary-expression before ‘=’ token

我在C ++ 11标准的第9.5节中没有看到禁止匿名联合的初始化程序,这让我觉得这是g ++的限制,可能在将来的版本中得到纠正。

这种限制是由语言还是通过g ++强加的,你可以通过给联盟命名来解决这个问题:

union { int i; float f; } obj = { 42 };

(但是你必须引用obj.iobj.f而不仅仅是if),或者使用作业而不是初始化程序:

union { int i; float f; };
i = 42;

(一旦我们解决了这种限制是由语言还是由编译器强加的话,我会清理这个答案。)