3

如果我在函数中声明一个匿名联合……</p>

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);
4

2 回答 2

5

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

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

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

您试图实现的(例如union { int i; float f; }{in};)不会编译,但假设它可以编译。然后,您将创建一个未命名类型的未命名对象(临时)。临时变量将在表达式结束时被销毁,因此该语句将无效。那么有什么意义呢?

于 2013-06-28T15:58:16.420 回答
2

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

在没有指定初始化器的情况下(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.iandobj.f而不仅仅是iand f),或者使用赋值而不是初始化器:

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

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

于 2013-06-28T17:56:13.857 回答