开发者

How does the compiler determine the location of a member when accessing through a base pointer

This just jumped into my head and I can't figure it out.

If I have a code like this:

struct A { char x[100]; };

struct B { int data; };

struct C : A, B {};

#include <iostream>
using namespace std;

B* get_me_some_stuff()
{
        static int x = 0;
        if (++x % 2 == 0)
                return new B();
        else
        开发者_如何学JAVA        return new C();
}

int main()
{
        B* x = get_me_some_stuff();
        B* y = get_me_some_stuff();

        x->data = 10;
        y->data = 20;

        cout << x->data << " " << y->data << endl;

        return 0;
}

How does the compiler determine the memory location of the data member?


Your x and y pointers actually point to the B subobject of the B and C objects (using the most-derived type).

Example:

int main() {
  C c;
  B *pb = &c; // converting the pointer here actually adjusts the address

  void *pvc = &c; // doesn't adjust, merely type conversion
  void *pvb = pb; // doesn't adjust, merely type conversion

  cout << boolalpha;
  cout << (pvc == pvb) << '\n'; // prints false
  cout << (&c == pb) << '\n'; // prints true!
                              // (&c is converted to a B* for the comparison)

  C *pc = static_cast<C*>(pb); // this static_cast, which is UB if pb doesn't
    // actually point to a C object, also adjusts the address

  cout << (pc == &c) << '\n'; // prints true

  return 0;
}

The moral of this story? Use static_cast from void* (not reinterpret_cast), and you can only convert from void to the exact same type that was originally used to convert to void:

reinterpret_cast<C*>(pvb)  // undefined behavior


Try this:

C* x = new C();
B* y = x;
cout << x << " " << y << endl;

Output for me:

0x1ae2010 0x1ae2074

The act of casting from C* to B* (or in the other direction) includes the necessary pointer arithmetic.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜