如果我在函数中声明匿名联合......
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);
答案 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.i
和obj.f
而不仅仅是i
和f
),或者使用作业而不是初始化程序:
union { int i; float f; };
i = 42;
(一旦我们解决了这种限制是由语言还是由编译器强加的话,我会清理这个答案。)