C/C++語言中的NULL
NULL不是C語言關鍵字,本質上是一個巨集定義。C++的編譯環境中,編譯器預先定義了一個巨集_cplusplus,程式中可以用條件編譯來判斷當前的編譯環境是C++的還是C的。
NULL的標準定義:
#ifdef _cplusplus // 條件編譯
#define NULL 0
#else
#define NULL (void *)0 // 這裡對應C語言的情況,NULL是一個表示式,是強制型別轉換為void *型別的0,本質是0
#endif
NULL的本質:NULL的本質是0,但是這個0不是當一個數字解析,而是當一個記憶體地址來解析的,這個0其實是0x00000000,代表記憶體的0地址。(void *)0這個整體表達式表示一個指標,這個指標變數本身佔4位元組,地址在哪裡取決於指標變數本身,但是這個指標變數的值是0,也就是說這個指標變數指向0地址(實際是0地址開始的一段記憶體)。
從指標角度理解NULL的本質
(1)int *p; // p是一個函式內的區域性變數,則p的值是隨機的,也就是說p是一個野指標。
(2)int *p = NULL; // p是一個區域性變數,分配在棧上的地址是由編譯器決定的,我們不必關心,但是p的值是(void *)0,實際就是0,意思是指標p指向記憶體的0地址處。這時候p就不是野指標了。
(3)為什麼要讓一個野指標指向記憶體地址0處?主要是因為在大部分的CPU中,記憶體的0地址處都不是可以隨便訪問的(一般都是作業系統嚴密管控區域,應用程式不能隨便訪問)。
為什麼需要NULL
(1)第一個作用就是讓野指標指向0地址處安全。
(2)第二個作用就是一個特殊標記。按照標準的指標使用步驟是:
int *p = NULL; // 定義p時立即初始化為NULL
p = xx;
if (NULL != p)
{
*p // 在確認p不等於NULL的情況下才去解引用p
}
p = NULL // 用完之後p再次等於NULL
注意:一般比較一個指標和NULL是否相等不寫成if (p == NULL),而寫成if (NULL == p)。原因是第一種寫法中如果不小心把寫成了=,則編譯器不會報錯,但是程式的意思完全不一樣了;而第二種寫法如果不小心把寫成了=則編譯器會發現並報錯。