Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do array elements count as a common initial sequence?

Sort of related to my previous question:

Do elements of arrays count as a common initial sequence?

struct arr4 { int arr[4]; };
struct arr2 { int arr[2]; };

union U
{
    arr4 _arr4;
    arr2 _arr2;
};

U u;
u._arr4.arr[0] = 0; //write to active
u._arr2.arr[0]; //read from inactive

According to this cppreference page:

In a standard-layout union with an active member of non-union class type T1, it is permitted to read a non-static data member m of another union member of non-union class type T2 provided m is part of the common initial sequence of T1 and T2....

Would this be legal, or would it also be illegal type punning?

like image 726
Weak to Enuma Elish Avatar asked Mar 17 '16 03:03

Weak to Enuma Elish


1 Answers

C++11 says (9.2):

If a standard-layout union contains two or more standard-layout structs that share a common initial sequence, and if the standard-layout union object currently contains one of these standard-layout structs, it is permitted to inspect the common initial part of any of them. Two standard-layout structs share a common initial sequence if corresponding members have layout-compatible types and either neither member is a bit-field or both are bit-fields with the same width for a sequence of one or more initial members.

As to whether arrays of different size form a valid common initial sequence, 3.9 says:

If two types T1 and T2 are the same type, then T1 and T2 are layout-compatible types

These arrays are not the same type, so this doesn't apply. There is no special further exception for arrays, so the arrays may not be layout-compatible and do not form a common initial sequence.

In practice, though, I know of a compiler (GCC) which:

  • ignores the "common initial sequence" rule, and
  • allows type punning anyway, but only when accesses are "via the union type" (as in your example), in which case the "common initial sequence" rule is obeyed indirectly (because a "common initial sequence" implies a common initial layout on the architectures the compiler supports).

I suspect many other compilers take a similar approach. In your example, where you type-pun via the union object, such compilers will give you the expected result - reading from the inactive member should give you value written via the inactive member.

like image 181
davmac Avatar answered Nov 15 '22 22:11

davmac