2

Empirically the following works (gcc and VC++), but is it valid and portable code?

typedef struct 
{
    int w[2];
} A;

struct B
{
    int blah[2];
};

void my_func(B b)
{
    using namespace std;
    cout << b.blah[0] << b.blah[1] << endl;
}

int main(int argc, char* argv[])
{

    using namespace std;

    A a;
    a.w[0] = 1;
    a.w[1] = 2;

    cout << a.w[0] << a.w[1] << endl;

    // my_func(a);                     // compiler error, as expected
    my_func(reinterpret_cast<B&>(a));  // reinterpret, magic?
    my_func(  *(B*)(&a) );             // is this equivalent? 

    return 0;
}
// Output:
// 12
// 12
// 12
  • Is the reinterpret_cast valid?
  • Is the C-style cast equivalent?
  • Where the intention is to have the bits located at &a interpreted as a type B, is this a valid / the best approach?

(Off topic: For those that want to know why I'm trying to do this, I'm dealing with two C libraries that want 128 bits of memory, and use structs with different internal names - much like the structs in my example. I don't want memcopy, and I don't want to hack around in the 3rd party code.)

Zero
  • 11,593
  • 9
  • 52
  • 70
  • personally, i just think of it as c++ equivalent of c-style cast – JosephH Apr 18 '12 at 06:38
  • possible duplicate of [Safety of casting between pointers of two identical classes?](http://stackoverflow.com/questions/7762929/safety-of-casting-between-pointers-of-two-identical-classes) – Juraj Blaho Apr 18 '12 at 07:19
  • @JurajBlaho I saw that, but the slight difference above is I'm not using pointers (in the reinterpret cast) - it was enough of a difference to make me at least want to double check it was valid. – Zero Apr 23 '12 at 00:19

1 Answers1

2

In C++11, this is fully allowed if the two types are layout-compatible, which is true for structs that are identical and have standard layout. See this answer for more details.

You could also stick the two structs in the same union in previous versions of C++, which had some guarantees about being able to access identical data members (a "common initial sequence" of data members) in the same order for different structure types.

In this case, yes, the C-style cast is equivalent, but reinterpret_cast is probably more idiomatic.

Community
  • 1
  • 1
John Calsbeek
  • 35,947
  • 7
  • 94
  • 101
  • From the linked answer, it seems that it is not *strictly* allowed in versions earlier than C++11, but 'probably works in practice'. Good enough for me! – Zero Apr 18 '12 at 07:14
  • 1
    To have a "common initial sequence", the names of the members must be identical too. (Officially, at least.) And g++ sometimes when out of its way to intentionally break code like that in the original posting. Which meant that the standard banned the use of the `union`, and g++ banned the use of `reinterpret_cast`. – James Kanze Apr 18 '12 at 07:42