一个表示0值的整数常量,叫做空指针常量。例如:0、0L、1-1(它们都是值为0的整数常量表达式)以及(void*)0、void* NULL 都是空指针常量,空指针常量可以赋值给任何指针类型,因为它是变体类型(void*)。但是我们更倾向于使用NULL表示这个空指针常量。对于其它方式(比如0)来表示空指针常量虽然不会产生任何问题,但是在根本意义上并不符合空指针常量的定义。因为空指针常量的存在意义还在强调它并不指向任何对象(后面会讲细节)。
空指针空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。
空指针是一个特殊的指针,因为这个指针不指向任何地方。这意味任何一个有效的指针如果和空指针进行相等的比较运算时,结果都是false。
在程序中,得到一个空指针最直接的方法就是运用预定义的NULL,这个值在多个头文件中都有定义。
如果要初始化一个空指针,我们可以这样,
int *ip = NULL;
int *ip = NULL;校验一个指针是否为一个有效指针时,我们更倾向于使用这种方式
if(ip != NULL)
if(ip != NULL) 而不是
if(ip)
if(ip) 为什么有人会用if(ip)这种方式校验一个指针非空,而且在C++中不会出现错误呢?而且现在很多人都会这样写。原因是这样的,
// Define NULL pointer value
#ifndef NULL
# ifdef __cplusplus
# define NULL 0
# else
# define NULL ((void *)0)
# endif
#endif // NULL
// Define NULL pointer value #ifndef NULL # ifdef __cplusplus # define NULL 0 # else # define NULL ((void *)0) # endif #endif // NULL在现在的C/C++中定义的NULL即为0,而C++中的true为≠0,所以此时的if(ip)和if(ip != NULL)是等效的。
NULL指针NULL是一个标准规定的宏定义,用来表示空指针常量。在C++里面被直接定义成了整数立即数的0,而在没有__cplusplus定义的前提下,就被定义成一个值是0的 void* 类型的指针常量
零指针零值指针,是值为0的指针,可以是任何一种类型的指针,可以是通用变体类型 void*,也可以是 char*, int* 等等。
在C++里面,任何一个概念都以一种语言内存公认的形式表现出来,例如std::vector会提供一个empty()子函数来返回容器是否为空,然而对于一个基本数值类型(或者说只是一个类似整数类型的类型)我们不可能将其抽象成一个类(当然除了auto_ptr等智能指针)来提供其详细的状态说明,所以我们需要一个特殊值来做为这种状态的表现。
C++标准规定,当一个指针类型的数值是0时,认为这个指针是空的。(我们在其它的标准下或许可以使用其它的特殊值来定义我们需要的NULL实现,可以是1,可以是2,是随实现要求而定的,但是在标准C++下面我们用0来实现NULL指针)
空指针指向内存的什么地方标准并没有对空指针指向内存中的什么地方这一问题作出规定,也就是说用哪个具体地址值表示空指针取决于系统实现。我们常见的空指针一般指向0地址,即空指针的内部用全0来表示(zero null pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体参见 C FAQ。
在实现编程中不需要了解在我们的系统上空指针到底是一个zero null pointer还是 nonzero null pointer,我们只需要了解一个指针是否是空指针就可以了——编译器会自动实现其中的转换,为我们屏蔽其中的实现细节。注意:不要把空指针的内部实现表示等同于整数0的对象表示——如上所述,有时它们是不同的。
对空指针实现的保护政策 逻辑地址和物理地址既然我们选择了0作为空的概念。在非法访问空的时候我们需要保护以及报错。因此,编译器和系统提供了很好的政策。