c - Is this use of unions strictly conforming? -


given code:

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

there exists 1 union object in entire program--q. active member set v1, , v2, , v1 again. code uses address-of operator on q.v1, or resulting pointer, when member active, , likewise q.v2. since p1, p2, , p3 same type, should legal use p3->v1 access p1->v1, , p3->v2 access p2->v2.

i don't see justify compiler failing output 1234, many compilers including clang , gcc generate code outputs 4321. think what's going on decide operations on p3 won't change contents of bits in memory, can ignored altogether, don't see in standard justify ignoring fact p3 used copy data p1->v1 p2->v2 , vice versa.

is there in standard justify such behavior, or compilers not following it?

i believe code conformant, , there flaw -fstrict-aliasing mode of gcc , clang.

i cannot find right part of c standard, same problem happens when compiling code in c++ mode me, , did find relevant passages of c++ standard.

in c++ standard, [class.union]/5 defines happens when operator = used on union access expression. c++ standard states when union involved in member access expression of built-in operator =, active member of union changed member involved in expression (if type has trivial constructor, because c code, have trivial constructor).

note write_s2x cannot change active member of union, because union not involved in assignment expression. code not assume happens, it's ok.

even if use placement new explicitly change union member active, ought hint compiler active member changed, gcc still generates code outputs 4321.

this looks bug gcc , clang assuming switching of active union member cannot happen here, because fail recognize possibility of p1, p2 , p3 pointing same object.

gcc , clang (and pretty every other compiler) support extension c/c++ can read inactive member of union (getting whatever potentially garbage value result), if access in member access expression involving union. if v1 not active member, read_s1x not defined behavior under implementation-specific rule, because union not within member access expression. because v1 active member, shouldn't matter.

this complicated case, , hope analysis correct, isn't compiler maintainer or member of 1 of committees.


Comments

Popular posts from this blog

ios - MKAnnotationView layer is not of expected type: MKLayer -

ZeroMQ on Windows, with Qt Creator -

unity3d - Unity SceneManager.LoadScene quits application -