Can you assign the value of one union member to another?

£可爱£侵袭症+ 提交于 2019-12-21 07:13:10

问题


Consider the following code snippet:

union
{
   int a;
   float b;
};

a = /* ... */;

b = a;               // is this UB?
b = b + something;

Is the assignment of one union member to another valid?


回答1:


Unfortunately I believe the answer to this question is that this operation on unions is under specified in C++, although self assignment is perfectly ok.

Self assignment is well defined behavior, if we look at the draft C++ standard section 1.9 Program execution paragraph 15 has the following examples:

void f(int, int);
void g(int i, int* v) {
    i = v[i++]; // the behavior is undefined
    i = 7, i++, i++; // i becomes 9

    i = i++ + 1; // the behavior is undefined
    i = i + 1; // the value of i is incremented

    f(i = -1, i = -1); // the behavior is undefined
}

and self assignment is covered in the i = i + 1 example.

The problem here is that unlike C89 forward which supports type-punning in C++ it is not clear. We only know that:

In a union, at most one of the non-static data members can be active at any time

but as this discussion in the WG21 UB study group mailing list shows this concept is not well understood, we have the following comments:

While the standard uses the term "active field", it does not define it

and points out this non-normative note:

Note: In general, one must use explicit destructor calls and placement new operators to change the active member of a union. — end note

so we have to wonder whether:

b = a;

makes b the active member or not? I don't know and I don't see a way to prove it with the any of the current versions of the draft standard.

Although in all practicality most modern compilers for example gcc supports type-punning in C++, which means that the whole concept of the active member is bypassed.




回答2:


I would expect that unless the source and destination variables are the same type, such a thing would be Undefined Behavior in C, and I see no reason to expect C++ to handle it any differently. Given long long *x,*y;, some compilers might process a statement like *x = *y >>8; by generating code to read all of *y, compute the result, and store it to *x, but a compiler might perfectly legitimately write code that copied parts of *y to *x individually. The standard makes clear that if *x and *y are pointers to the same object of the same type, the compiler must ensure that no part of the value gets overwritten while that part is still needed in the computation, but compilers are not required to deal with aliasing in other situations.



来源:https://stackoverflow.com/questions/22022826/can-you-assign-the-value-of-one-union-member-to-another

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!