c++reinterpret-cast

Reinterpret cast of void * didn't do what I thought it would


I am trying to create a reference to a struct in an arbitrary block of memory pointed to by a void pointer. But I cant seem to work it out!

Given the example code below (tested on clang latest), I find that my reference is initialised to the address of the void pointer itself, rather than the value of the void pointer. Please help me understand what I dont!

#include <iostream>

int main(void)
{
    struct Test
    {
        int a;
        void * p;
        unsigned x[10];
    };

    struct It
    {
        unsigned y[10];
    };

    Test t;
    t.p = &t.x;

    auto & s = reinterpret_cast<It &>(t.p);
    
    std::cout << std::hex << "&t=" << &t << ", &t.p=" << &t.p << ", p=" << t.p << ", s=" << (void*)&s << std::endl;
}

I get the output:

&t=0x7ffd4fbac9f8, &t.p=0x7ffd4fbaca00, p=0x7ffd4fbaca08, s=0x7ffd4fbaca00

As you can see s references memory at the address of t.p. I was expecting the reference to be the same as the value of t.p.

To extend this further, the result is different if you change the cast line to:

auto a = t.p;
auto & s = reinterpret_cast<It &>(a);

Then you get:

&t=0x7ffc31e65578, &t.p=0x7ffc31e65580, p=0x7ffc31e65588, s=0x7ffc31e65570

Where the reference s is set to the address of t.

More of a learning question than anything but would be good to understand for the future.


Solution

  • reinterpret_cast<T &>(x) is equivalent to *reinterpret_cast<T *>(&x) (except the former doesn't respect overloaded &, which makes it useful for implementing std::addressof).

    So if you had a different pointer type that can be dereferenced, you could do reinterpret_cast<It &>(*t.p). But since void * can't be dereferenced, your only option is *reinterpret_cast<It *>(t.p).