C++ 初始化匿名联合的语法

C++ 初始化匿名联合的语法,c++,unions,C++,Unions,如果我在函数中声明匿名联合 void f(int in) { union { int i; float f; }; // … } …是否存在初始化它的语法(除了在另一个语句中指定给i或f之外)?快速查看规范表明不存在。明显的语法不会编译: // Nope: union { int i = in; float f; }; union { int i; float f; } = in; union { int i; float f; } = {in}; union { int i;

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

void f(int in) {
    union { int i; float f; };
    // …
}
…是否存在初始化它的语法(除了在另一个语句中指定给
i
f
之外)?快速查看规范表明不存在。明显的语法不会编译:

// 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);
这项工作(至少在gcc 4.7.2中):

请注意,该类型(即
联合
)是匿名的,但其实例名为
x


您试图实现的(例如,
union{int i;float f;}{in};
)没有编译,但假设它编译了。然后您将创建一个未命名的对象(临时对象)属于未命名类型。临时值将在表达式末尾被销毁,因此,此语句将无效。那么这有什么意义呢?

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

在指定初始化器的缺省情况下(在C中添加到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允许匿名联盟和结构,但是只有当包围联盟或Stutc+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.i
obj.f
,而不仅仅是
i
f
),或者使用赋值而不是初始值设定项:

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

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

它必须是匿名的吗?我现在没有编译器来测试它,但是请尝试
union{int I;float f;}={in};
@EranZimmerman:这两个都无法用“错误:在联合后应为“;”@JoachimPileborg很好,命名这将是一个完全合法的解决方法。我已经自由编辑了您的代码,以便您的声明实际声明对象(
obj
),而不仅仅是类型。如果您认为编辑无效,请随意还原或重新编辑。我不想只初始化第一个命名成员,所以您的第一个示例就可以了,但我想问的是匿名联盟(请参阅我对您评论的回复)。这是一个匿名类型,但它不是匿名联合。示例编译-其成员位于父作用域中!我只是在定义中寻找初始化它们的语法,而不是稍后分配给它们。
union { int i; float f; };
i = 42;