您现在的位置: 万盛学电脑网 >> 程序编程 >> 网络编程 >> 编程语言综合 >> 正文

NULL指针\零指针、野指针

作者:佚名    责任编辑:admin    更新时间:2022-06-22

野指针:“野指针”不是NULL指针,是指向“垃圾”内存(不可用内存)的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if无法判断一个指针是正常指针还是“野指针”。

 “野指针”的成因主要有三种:

  1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如:
     char *p = NULL;
     char *str = (char *) malloc(100);

  2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。

free和delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉。 free以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不把p设置为NULL,会让人误以为p是个合法的指 针。如果程序比较长,我们有时记不住p所指的内存是否已经被释放,在继续使用p之前,通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。

? char *p = (char *) malloc(100); strcpy(p, “hello”); free(p);            // p 所指的内存被释放,但是p所指的地址仍然不变       if(p != NULL)      // 没有起到防错作用 {     strcpy(p, “world”);      // 出错 }

  3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:

? class A {      public:      void Func(void){ cout << “Func of class A” << endl; } }; void Test(void) {     A *p;    {       A a;       p = &a; // 注意 a 的生命期 ,只在这个程序块中(花括号里面的两行),而不是整个test函数    }      p->Func();  // p是“野指针” }

  函数Test在执行语句p->Func()时,对象a已经消失,而p是指向a的,所以p就成了“野指针”。

 

1. 空指针、NULL指针、零指针

1.1什么是空指针常量

0、0L、''、3 - 3、0 * 17 (它们都是“integer constant expression”)以及 (void*)0 (我觉得(void*)0应该算是一个空指针吧,更恰当一点)等都是空指针常量(注意 (char*) 0 不叫空指针常量,只是一个空指针值)。至于系统选取哪种形式作为空指针常量使用,则是实现相关的。一般的 C 系统选择 (void*)0 或者 0 的居多(也有个别的选择 0L);至于 C++ 系统,由于存在严格的类型转化的要求,void* 不能象 C 中那样自由转换为其它指针类型,所以通常选 0 作为空指针常量(C++标准推荐),而不选择 (void*)0。

1.2 什么是空指针

如果 p 是一个指针变量,则 p = 0; p = 0L; p = ''; p = 3 - 3; p = 0 * 17; 中的任何一种赋值操作之后(对于 C 来说还可以是 p = (void*)0;), p 都成为一个空指针,由系统保证空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。(比如这里的(void*)0就是一个空指针。把它理解为null pointer还是null pointer constant会有微秒的不同,当然也不是紧要了)。其实空指针只是一种编程概念,就如一个容器可能有空和非空两种基本状态。

1.3 NULL指针

  NULL指针是不指向任何一个地址的指针。这样的指针一般是允许的。当一个指针为NULL的时候,不要对它进行存取。

  NULL 是一个标准规定的宏定义,用来表示空指针常量。因此,除了上面的各种赋值方式之外,还可以用 p = NULL; 来使 p 成为一个空指针。

(很多系统中的实现:#define NULL (void*)0,与这里的“a null pointer constant”并不是完全一致的)

C++标准库定义的NULL指针

? // Define   NULL   pointer   value #ifndef   NULL #   ifdef   __cplusplus #     define   NULL      0 #   else #     define   NULL      ((void   *)0) #   endif #endif //   NULL

  

NULL是一个宏,在C++里面被直接被定义成了整数立即数类型的0,而在没有__cplusplus定义的前提下,就被定义成一个值是0的void   *类型指针常量。

1.4 零指针

零值指针,是值为0的指针,可以是任何一种指针类型,可以是通用变体类型void*,也可以是char*,int*等等。

在C++里面,任何一个概念都要以一种语言内存公认的形式表现出来,例如std::vector会提供一个empty()子函数来返回容器是否为 空,然而对于一个基本数值类型(或者说只是一个类似整数类型的类型)我们不可能将其抽象成一个类(当然除了auto_ptr等只能指针)来提供其详细的状 态说明,所以我们需要一个特殊值来做为这种状态的表现。 
C++标准规定,当一个指针类型的数值是0时,认为这个指针是空的。(我们在其他的标准下或许可以使用其他的特殊值来定义我们需要的NULL实现,可以是1,可以是2,是随实现要求而定的,但是在标准C++下面我们用0来实现NULL指针)

1.5 空指针向了内存的什么地方(空指针的内部实现)?