当通过基指针访问时,编译器如何确定成员的位置

时间:2010-10-27 01:04:28

标签: c++

这只是跳进了我的脑海,我无法理解。

如果我有这样的代码:

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
                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;
}

编译器如何确定data成员的内存位置?

2 个答案:

答案 0 :(得分:4)

你的x和y指针实际指向B和C对象的B子对象(使用派生最多的类型)。

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;
}

这个故事的寓意?使用void *( not reinterpret_cast)中的static_cast,您只能将void转换为最初用于转换为void的完全相同的类型:

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

答案 1 :(得分:2)

试试这个:

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

为我输出:

0x1ae2010 0x1ae2074

C*转换为B*(或在另一个方向)的行为包括必要的指针算法。