请参阅下面的更新——我不确定这是语言限制还是编译器限制。
在没有指定初始化器的情况下(1999 年添加到 C 中,据我所知目前在 C++ 中不存在),联合的初始化器只能为第一个命名成员指定一个值:
union { int i; float f; } obj = { 42 }; // sets obj.i to 42
从 1999 年的标准开始,C 提供了指定的初始化程序,让您可以初始化任何您喜欢的命名成员:
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
andobj.f
而不仅仅是i
and f
),或者使用赋值而不是初始化器:
union { int i; float f; };
i = 42;
(一旦我们解决了这个限制是由语言还是由编译器强加的,我会清理这个答案。)