c 指標中0,NULL和nullptr

2021-08-07 14:47:17 字數 2658 閱讀 6870

在c語言中,我們使用null表示空指標,也就是我們可以寫如下**:

int *i =null;

foo_t *f = null;

實際上在c語言中,null通常被定義為如下:

#define null ((void *)0)
也就是說null實際上是乙個void *的指標,然後吧void *指標賦值給int *和foo_t *的指標的時候,隱式轉換成相應的型別。而如果換做乙個c++編譯器來編譯的話是要出錯的,因為c++是強型別的,void *是不能隱式轉換成其他指標型別的,所以通常情況下,編譯器提供的標頭檔案會這樣定義null:

#ifdef __cplusplus ---簡稱:cpp c++ 檔案

#define null 0

#else

#define null ((void *)0)

#endif

因為c++中不能將void *型別的指標隱式轉換成其他指標型別,而又為了解決空指標的問題,所以c++中引入0來表示空指標(注:0表示,還是有缺陷不完美),這樣就有了類似上面的**來定義null。實際上c++的書都會推薦說c++中更習慣使用0來表示空指標而不是null,儘管null在c++編譯器下就是0。為什麼c++的書都推薦使用0而不是null來表示空指標呢?我們看乙個例子:

在foo.h檔案中宣告了乙個函式:

void bar(sometype1 a, sometype2 *b);
這個函式在a.cpp、b.cpp中呼叫了,分別是:

a.cpp:

bar(a, b);
b.cpp:

bar(a, 0);
好的,這些**都是正常完美的編譯執行。但是突然在某個時候我們功能擴充套件,需要對bar函式進行擴充套件,我們使用了過載,現在foo.h的宣告如下:

void bar(sometype1 a, sometype2 *b);

void bar(sometype1 a, int i);

這個時候危險了,a.cpp和b.cpp中的呼叫**這個時候就不能按照期望的執行了。但是我們很快就會發現b.cpp中的0是整數,也就是在overload resolution的時候,我們知道它呼叫的是void bar(sometype1 a, int i)這個過載函式,於是我們可以做出如下修改讓**按照期望執行:

bar(a, static_cast(0));  --- 我們的遊戲專案就遇到這個問題,這樣用開起來彆扭
我知道,如果我們一開始就有bar的這兩個過載函式的話,我們會在一開始就想辦法避免這個問題(不使用過載)或者我們寫出正確的呼叫**,然而後面的這個過載函式或許是我們幾個月或者很長一段時間後加上的話,那我們出錯的可能性就會加大了不少。貌似我們現在說道的這些跟c++通常使用0來表示空指標沒什麼關係,好吧,假設我們的呼叫**是這樣的:

foo.h

void bar(sometype1 a, sometype2 *b);
a.cpp

bar(a, b);
b.cpp

bar(a, null);
當bar的過載函式在後面加上來了之後,我們會發現出錯了,但是出錯的時候,我們找到b.cpp中的呼叫**也很快可能忽略過去了,因為我們用的是null空指標啊,應該是呼叫的void bar(sometype1 a, sometype2 *b)這個過載函式啊。實際上null在c++中就是0,寫null這個反而會讓你沒那麼警覺,因為null不夠「明顯」,而這裡如果是使用0來表示空指標,那就會夠「明顯」,因為0是空指標,它更是乙個整形常量。

在c++中,使用0來做為空指標會比使用null來做空指標會讓你更加警覺。

雖然上面我們說明了0比null可以讓我們更加警覺,但是我們並沒有避免這個問題。這個時候c++ 11的nullptr就很好的解決了這個問題,我們在c++ 11中使用nullptr來表示空指標,這樣最早的**是這樣的,

foo.h

void bar(sometype1 a, sometype2 *b);
a.cpp

bar(a, b);
b.cpp

bar(a, nullptr);
在我們後來把bar的過載加上了之後,**是這樣:

foo.h

void bar(sometype1 a, sometype2 *b);

void bar(sometype1 a, int i);

a.cpp

bar(a, b);
b.cpp

bar(a, nullptr);
這時候,我們的**還是能夠如預期的一樣正確執行。

在沒有c++ 11的nullptr的時候,我們怎麼解決避免這個問題呢?我們可以自己實現乙個(《imperfect c++》上面有乙個實現):

const

class

nullptr_t

template

inline

operator t c::*() const

private

:

void

operator&() const

;} nullptr = {};

雖然這個東西被大家討論過很多次了,但是我覺得還是有必要再討論一下,畢竟在c++ 11還沒有普及之前,我們還是應該知道怎麼去避免問題,怎麼很快的找到問題。

php中0, ,null和false的區別

php中很多還不懂php中0,null和false之間的區別,這些區別有時會影響到資料判斷的正確性和安全性,給程式的測試執行造成很多麻煩。先看乙個例子 str1 null str2 false echo str1 str2 相等 不相等 str3 str4 0 echo str3 str4 相等 不...

php中0, ,null和false的區別

php中很多還不懂php中0,null和false之間的區別,這些區別有時會影響到資料判斷的正確性和安全性,給程式的測試執行造成很多麻煩。先看乙個例子 str1 null str2 false echo str1 str2 相等 不相等 str3 str4 0 echo str3 str4 相等 不...

php中0, ,null和false的區別

php中很多還不懂php中0,null和false之間的區別,這些區別有時會影響到資料判斷的正確性和安全性,給程式的測試執行造成很多麻煩。先看乙個例子 str1 null str2 false echo str1 str2 相等 不相等 str3 str4 0 echo str3 str4 相等 不...