2009年10月31日 星期六

NULL

 
當指標不指向任何東西時,呈 nil 狀態,可用 0 表示。
早期,C 程式師不喜歡見到意味不明的 magic number,
何況 0 身兼多義,既是 0、0x0、00、0.f、0u、'\0',
也是 (void*)0,
故偏好使用巨集 NULL 來描述 (void*)0 這個狀態。

*註:雖然上述表示都可視為 0,
但他們的資料型別並不相同。
在 32 bits OS 上,「常見」的規格為:
'\0' 為 char,占 1 Byte。
0, 00, 0x0 為 int,占 4 Byte。
0u 為 unsigned int,占 4 Byte。
0.f 為 double,占 4 Bytes。
0.0 為 double,占 8 Bytes。

而早期寫 C++ 程式的前輩們,多數偏好以 0 來表示
const null pointer,因為看起來較簡潔。
因此在 C++ 中便做了如下定義:
#ifdef __CPLUSPLUS #define NULL 0 #else #define NULL (void *)0 #endif
而 C++ 0x 則多了新關鍵字 nullptr 來描述 null pointer,
目前較新的 Compiler 皆有支援此 keyword。

------

C++ 中,因以往 C 的 NULL 定義會轉成像 int* p1 = (void*)0;
造成型別不相容,故便將 NULL 定成 0。

為何是 0? 因為 0 具有常數性,其指涉至 invalid memory,
對這區域中的 I/O 存取,皆被檢驗為不合法,
此時程式被中斷,秀出出錯原因 (與程式碼段)。
(在 JVM 上便是丟出 NullPointerException)

而 (void*)0 並不具常數性,仍可對位址 0 進行 I/O 存取,
如 Christopher McGee 列舉的:
*(NULL) NULL->member NULL[1] NULL->function() strcpy( NULL, "abc" ) *(NULL)(params);
之後可能造成記憶體毀損,程式 broken,
顯示「記憶體存取錯誤」的 dialog。

若您用的是 C++ 編譯器,直接打 0、NULL,
或 Herb Sutter 提出的 nullptr 都沒問題,
視之個人習慣,只要讓 pointer 不 dangling 便行。
除非你所處的多人合作環境中,對處理 null pointer 已有共識,
這時理應遵循此共識。

若是用 C++/CLR,由於 Object^ obj = 0;
會產生 implicit boxing of 0,也就是隱含的實體物件。
為方便追蹤 obj 的初始化與指派行為,
需寫成 Object^ obj = nullptr;
表示 refer to no object。

沒有留言:

張貼留言