多重继承中,求基类对象相对子类对象地址偏移的问题,为什么以地址0x```0的时候会失败

enic 2009-12-18 11:02:24
#include <windows.h>
#include <iostream>
using namespace std;

class Base1
{
public:
virtual void f() { }
};

class Base2
{
public:
virtual void f() { }
};

class Base3
{
public:
virtual void f() { }
};

class Drive : public Base1, public Base2, public Base3
{
};

// any non zero value because multiply zero with any no is zero
#define SOME_VALUE 8 // 可以用除了0以外的任何数字,但是为什么就不能用0

int main()
{
// Drive* pd = (Drive*)1; // 欺骗编译器在地址0x00000001出有一个Drive对象
cout<<(DWORD)static_cast<Base1*>((Drive*)SOME_VALUE)-SOME_VALUE<< endl;
cout<<(DWORD)static_cast<Base2*>((Drive*)SOME_VALUE)-SOME_VALUE<< endl;
cout<<(DWORD)static_cast<Base3*>((Drive*)SOME_VALUE)-SOME_VALUE<< endl;
return 0;
}
...全文
175 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
enic 2009-12-19
  • 打赏
  • 举报
回复
也就是static_cast隐藏了操作···


结贴

去找gcc理论
老邓 2009-12-18
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 cl_gamer 的回复:]
static_cast <SomeType> (0)    // 强制将0转换为某种类型


这里还有另一个经典的例子


#define  offsetof(struct_t,member)  ((size_t)(char  *)&((struct_t  *)0)->member)
结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:   
  #define  offsetof(s,m)  (size_t)&(((s  *)0)->m)   
  例如,想要获得S2中c的偏移量,方法为   
  size_t  pos  =  offsetof(S2,  c);//  pos等于4   
 [/Quote]
区别在于,这种计算不需要隐式转换。
只要知道内存布局即可!
enic 2009-12-18
  • 打赏
  • 举报
回复
洗洗先睡了

明天上来继续
enic 2009-12-18
  • 打赏
  • 举报
回复
可能我表达有问题


我觉得后面的
((struct_t *)0)->member
这里的NULL生效了
mmilmf 2009-12-18
  • 打赏
  • 举报
回复

http://www.vckbase.com/document/viewdoc/?id=1651

这个讲的比较详细,参看下吧
enic 2009-12-18
  • 打赏
  • 举报
回复
static_cast <SomeType> (0) // 强制将0转换为某种类型


这里还有另一个经典的例子


#define offsetof(struct_t,member) ((size_t)(char *)&((struct_t *)0)->member)
结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
例如,想要获得S2中c的偏移量,方法为
size_t pos = offsetof(S2, c);// pos等于4






失落的凡凡 2009-12-18
  • 打赏
  • 举报
回复
0x00和0只是我们看起来有区别,在编译器看来都是一模一样的…… 都表示空指针
老邓 2009-12-18
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 cl_gamer 的回复:]
嗯,一个问题解决了。


接下来是static_cast <SomeType> (0)

这个应该怎么处理?

[/Quote]
不明白你的意图。
因为SomeType不知道是啥。
enic 2009-12-18
  • 打赏
  • 举报
回复
嗯,一个问题解决了。


接下来是static_cast<SomeType> (0)

这个应该怎么处理?
老邓 2009-12-18
  • 打赏
  • 举报
回复
我理解为:NULL地址虽然可以访问,但明显非法的。
所以,Relase编译后运行时,会导致内存越界,返回一个0x00000005错误。

编译器在针对多重继承的隐式转换既然需要考虑其内存布局,自然会检查该指针的合法性。
如果指针不合法,则不做任何转换,结果就是:0-0=0了。
老邓 2009-12-18
  • 打赏
  • 举报
回复
http://ju-kevin.spaces.live.com/blog/cns!907BD90CD611C0C7!329.entry
看看这个,关于多重继承的内存结构。

在隐式转换时,编译器会根据多重继承的内存布局改变指针的地址。
enic 2009-12-18
  • 打赏
  • 举报
回复
不可能认为 0x~~0 地址是不可用的吧

linux引导的最后一步就是拷贝自己到0x~~0处
enic 2009-12-18
  • 打赏
  • 举报
回复
NULL指针 我理解的,NULL无效,我们YY出来的衍生意思(每次都是自己判断的对吧)
实际上 地址0x~~~0是可用地址对吧?一写平台的操作系统代码都是从这里开始


因为作者给出的注释有一句:
any non zero value because multiply zero with any no is zero
所以我怀疑static_cast实现细节是否跟当前地址有关,而且用到了乘法指令
这个推断也是有根据的,应为在static_cast转换是可能改变地址的

这里可能会是编译器优化还是,或者这么问
编译器中static_cast的实现细节是什么

pengzhixi 2009-12-18
  • 打赏
  • 举报
回复
你判断指针是否为空是怎么判断的呢?
老邓 2009-12-18
  • 打赏
  • 举报
回复
我的意思是:即使你要欺骗编译器,你也要给一个非NULL指针。
这样,编译器才认定这是一个有效的指针,从而进行隐式转换。
老邓 2009-12-18
  • 打赏
  • 举报
回复
SOME_VALUE如果是0,也就是说:这是一个NULL指针。
那样,编译器不会傻到将一个NULL指针进行隐式转换吧?

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧