c++ 由类型转换引起的指针偏移

由于转载了另外的转载,且原文暂时未找到,此处无法列出原文地址。


在C语言中,如果对一个指针做类型转换,不会改变这个指针的值,改变的只是对指针的解释方式。但是在C++中,由于一些特性的引入,在对指针做类型转换时,编译器有时不得不对指针做一个偏移,以支持这些特性。下面将具体讨论这些情况。
1. 由虚函数引起的指针偏移
通常在有虚函数的类中,编译器会安插一个vptr,但是对vptr的位置C++语言并未做出明确的规定,就目前的实现来看,有的编译器将vptr放在类的开头,如microsoft的c++编译器,而有的编译器将vptr放在类的末尾,如cfront。
对于将vptr放在类的开头这种编译器,我们考虑如下两个类:

class X {
    int i;     
};
class Y : public X {
    int j;
public:
    virtual void vf();
};


X的内存布局很简单,由于它没有虚函数,所以没有vptr,只有一个int类型的变量i;
而Y的内存布局可能像这样:
vptr
 int i
 int j
对于下面这样的代码:
Y y;
X* pX = &y;
编译器为了保证将Y类型的指针转换为X类型的指针后,指向的是一个有效的X对象,它将不得不做一个偏移,实际的代码可能像这样:
X* pX = (X*)((char*)&y + sizeof(vptr))

2. 由多重继承引起的指针偏移
首先需要说明一下多重继承的内存布局,虽然C++语言未明确做出规定,但目前的多数实现会按照基类声明的顺序依次将每个基类的数据成员顺次放入派生类。例如:
class A {
    int i;
};
class B {
    int j;
};
class C : public A, public B {
    int k
};


C的内存布局可能像这样:
 int i
 int j
 int k
有了这样的布局,很容易就能猜到编译器在做类型转换时对指针做出的偏移,例如
C c;
B* pb = &c;
猜想实际的代码可能是:
B* pb = (B*)((char*)&c + sizeof(A));
对于例子中的情况,上面的猜想是成立的,但对于一般的情况就不成立了。在将C类型的指针转换的时候,这个C类型的指针有可能为空,按上面的转换思路,那空指针也得加一个偏移量了,为了避免这种情况,实际的代码可能会是这样:
B* pb = (pc) ? (B*)((char*)pc + sizeof(A)) : 0; //假设pc是一个指向C的指针

3.由虚继承引起的指针偏移
对 于一般的继承(这里仅指单继承),在不涉及虚函数的情况下,由于编译器的实现多会将基类数据成员排在派生类之前,所以从派生类指针转换为基类指针时,一般 不需要做偏移。但是对于虚继承,情况就不一样了。由于虚基类的地址是在运行时确定的,所以由派生类的指针转换为虚基类的指针时必然会引起偏移。虚基类有多 种实现方式,所以在这儿就先不举例了。可以参考<Inside the C++ Object Model>.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值