On Fri, Oct 27, 2017 at 9:00 AM, Yubin Ruan <ablacktsh...@gmail.com> wrote: > ... > On Mon, Sep 25, 2017 at 01:41:55PM -0700, Myriachan wrote: >> This question that "supercat" posted on Stack Overflow ran into an >> interesting problem: >> >> https://stackoverflow.com/questions/46205744/is-this-use-of-unions-strictly-conforming/ >> >> A copy of the code involved is as follows: >> >> struct s1 {unsigned short x;}; >> struct s2 {unsigned short x;}; >> union s1s2 { struct s1 v1; struct s2 v2; }; >> >> static int read_s1x(struct s1 *p) { return p->x; } >> static void write_s2x(struct s2 *p, int v) { p->x=v;} >> >> int test(union s1s2 *p1, union s1s2 *p2, union s1s2 *p3) >> { >> if (read_s1x(&p1->v1)) >> { >> unsigned short temp; >> temp = p3->v1.x; >> p3->v2.x = temp; >> write_s2x(&p2->v2,1234); >> temp = p3->v2.x; >> p3->v1.x = temp; >> } >> return read_s1x(&p1->v1); >> } >> int test2(int x) >> { >> union s1s2 q[2]; >> q->v1.x = 4321; >> return test(q,q+x,q+x); >> } >> #include <stdio.h> >> int main(void) >> { >> printf("%d\n",test2(0)); >> } >> >> >> Both GCC and Clang in -fstrict-aliasing mode with optimizations are acting >> as if they ran into undefined behavior, and return 4321 instead of the >> expected 1234. This happens in both C and C++ mode. Intel C++ and Visual >> C++ return the expected 1234. All four compilers hardwire the result as a >> constant parameter to printf rather than call test2 or modify memory at >> runtime.
C++ is different than C, and C++ is more strict. Unlike C, you cannot access the inactive members of a union in C++. It is undefined behavior. If you compile with Sun's C++ compiler it actually issues a warning for doing so. Clang, GCC, ICC and MSVC does not issue a warning. Also see https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior. Jeff