令人惊讶的NULL类指针

一.NULL指针

NULL,在C/C++常用来表示空指针,即指向地址为0的指针。
通常在指针初始化 或者 释放指针所指向空间后,将指针置为NULL,防治导致悬浮指针也使其表明自己未指向分配的空间。
这样看来指向NULL的指针仅仅如此?
当然我们也常常用一些小技巧来做一些很实用的事情比如,求Struct中某个变量的偏移位置:
#define VALUEOFFSET(sType, vName)   (int)(&((sType *)NULL)->vName)
即使指向空的指针也能为我们程序做这么多事情,真有意思;而本人遇到的令人惊讶的问题,也和NULL指针扯上了关系。

二.NULL空类指针

先来看一段代码:
#include <iostream>
using namespace std;
class Base
{
public:
	Base(){;}
	void Suprise()
	{
		cout << "Suprise" << endl;
	}
};
void main()
{
	Base *pTest = NULL;
	pTest->Suprise();
	return;
}
在谨慎的阅读完这段代码后,或许能够做出正确的判断,但给人的第一感觉运行错误。
(直觉是人根据以往的经验和现场的环境做出的迅速的判断,慢慢的分析后得出的结果反而未必更加接近答案。)
但这次的确直觉错了,程序能够正常运行,并且能够很顺利的打印出"Suprise";

三.空类指针的函数调用分析

(1)仔细分析示例代码后,会发现Suprise()成员函数地址是不变的(非虚函数,无需动态绑定),在编译阶段根据pTest的指针类型就能得出Suprise()函数调用的地址;进行调用,汇编代码更加清晰得证明了这一点:
	Base *pTest = NULL;
004119FE  mov         dword ptr [pTest],0 
	pTest->Suprise();
00411A05  mov         ecx,dword ptr [pTest] 
00411A08  call        Base::Suprise (411032h) 
如果是虚函数,我们这需要根据其指向的对象的虚表指针和虚函数偏移找到其相应的函数体入口,这个过程也成为动态绑定过程。

(2)除了(1)保证了函数的正确执行,其实还隐含了一个条件,那就是在pTest->Suprise中并没有对其成员变量进行操作。
因为Suprise函数隐含了This指针,没有对成员变量进行操作,那么This指针为NULL也不会产生内存访问冲突错误。
void Suprise(Base * const this)

综合上述:Suprise的非虚函数和函数中没有对成员变量进行操作保证了NULL类指针成功对方法的调用。



评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值