工会成员之间的分配

时间:2015-08-05 05:09:04

标签: c++ language-lawyer unions

这段代码定义明确吗?

int main()    
{    
    union     
    {    
        int i;    
        float f;    
    } u;    

    u.f = 5.0;    
    u.i = u.f;       // ?????
}    

它在一个表达式中访问两个不同的union成员,所以我想知道它是否违反了关于活动成员的[class.union] / 1条款。

C ++标准似乎低估了哪些操作会更改内置类型的活动成员,以及如果读取或写入非活动成员会发生什么。

3 个答案:

答案 0 :(得分:6)

  

赋值运算符(=)和复合赋值运算符从右到左分组。 [...]在所有情况下,赋值在右侧和左侧操作数的值计算之后排序,并且在值计算之前赋值表达式。 [...]

     

[N4431§5.18/ 1]

在你的情况下,左手边的值计算(仅涉及成员访问,而不是读取)的前提是导致未定义的行为,我将如下应用如下:

  1. 右侧的值计算读取u.f,它是联合的活动成员。所以一切都很好。
  2. 执行分配。这涉及将获得的结果写入u.i现在更改了联合的活跃成员。

答案 1 :(得分:4)

可以写入非活动成员。事实上,这是使它们变得活跃的唯一方法。活跃会员没有限制;它可以读写。

可以获取非活动成员的地址。这是执行写入的有效方法:

union {
  int i;
  float f;
} u;
float* pf = &u.f; // Does NOT change the active member.
u.i = 3;
*pf = 3.0; // Changes the active member.

在您的示例中,活动成员只能通过向其u.i写入5,这意味着必须已读取值u.f

答案 2 :(得分:-2)

通过查看[class.union] / 1,从包含标准布局联合的标准布局联合的考虑因素共享一个共同的初始序列,这意味着以下是可以的

int main()
{
   union 
   {
      union 
      {
          int x ;
          float y ;
      } v ;
      union 
      {
          int x ;
          double z ;
      } w ;      
   } u ;

   u.v.x = 2 ;
   int n = u.w.x ; // n contains 2
}

这里常见的初始序列是int x ;

这不是问题所在,但告诉我们这种混合是可以的。