萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 編程語言綜合 >> NULL指針\零指針、野指針

NULL指針\零指針、野指針

野指針:“野指針”不是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 空指針向了內存的什麼地方(空指針的內部實現)?

copyright © 萬盛學電腦網 all rights reserved