user183833 user183833 - 2 months ago 8
C++ Question

Struct alignment and type reinterpretation

Lets say I have two types A and B.

Then I make this type

struct Pair{
A a;
B b;
};


Now I have a function such as this.

void function(Pair& pair);


And lets assume that
function
will only ever use the
a
part of the pair.

Then is it undefined behavior to use and call the function in this way?

A a;
function(reinterpret_cast<Pair&>(a));


I know that a compiler may insert padding bytes after a member but can it also do it before the first member?

Answer

I think it's defined behavior, assuming Pair is standard-layout. Otherwise, it's undefined behavior.

First, a standard layout class and its first member share an address. The new wording in [basic.compound] (which clarifies earlier rules) reads:

Two objects a and b are pointer-interconvertible if:
* [...]
* one is a standard-layout class object and the other is the first non-static data member of that object, or, [...]
* [...]
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast (5.2.10).

Also from [class.mem]:

If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member. Otherwise, its address is the same as the address of its first base class subobject (if any).

So the reinterpret_cast from A to Pair is fine. If then function only ever access the a object, then that access well-defined, as the offset of A is 0, so the behavior is equivalent to having function take an A& directly. Any access to the b would be undefined, obviously.


However, while I believe the code is defined behavior, it's a bad idea. It's defined behavior NOW, but somebody someday might change function to refer to pair.b and then you're in a world of pain. It'd be a lot easier to simply write:

void function(A& a) { ... }
void function(Pair& p) { function(p.a); }

and just call function directly with your a.