天天看點

空指針的深入了解(C/C++)

空指針究竟指向了記憶體的哪個地方?

如果僅僅聲明一個指針,而沒有任何指派,那麼這個指針是野指針,它會指到VM的任何位置,碰到異常操作,比如對隻讀區寫操作,就會引起硬體中斷産生core,也就是通常的段錯誤。

良好的程式設計風格是将指針永遠都可控,也就是這個指針的位址,程式可控,通常,對于不使用或初始的指針都将其位址置為0,這是約定俗成的,就如同,我們經常使用的進制一樣,你非用一個别人都不用的進制表示數,那也随你,隻是别人覺得怪而已。再比如,用free釋放完指針後,相信大家都會将指針置成NULL或0,就是為了再使用這個指針時,便于判斷。指針的位址為0,操作起來就非常友善,比較位操作等,都可對應到機器碼,這也就展現了“進階彙編”的美譽。用NULL宏,僅僅是為了可讀性,編譯器會進行優化的。

對于将NULL定義成某個位址,然後進行比較,相對NULL為0位址,然後比較,性質是相同的,在執行過程中,如果重新定義的位址為可操作,可能會對程式的邏輯流程産生影響。

=========================================================================================

《C陷阱與缺陷》3.5節:

永遠不能對空指針解引用!!!

如果将0賦給一個指針,絕對不能使用該指針指向的内容!!!

空指針的簡單描述:

它 “與任何對象或函數的指針值都不相等”。也就是說, 取位址操作符 & 永遠也不能得到空指針, 同樣對 malloc() 的成功調用也不會傳回空指針, 如果失敗, malloc() 的确傳回空指針, 這是空指針的典型用法:表示 “未配置設定”或者 “尚未指向任何地方”的指針。

========================================================================================

空指針和未初始化的指針:

空指針在概念上不同于未初始化的指針。空指針可以確定不指向任何對象或函數; 而未初始化指針則可能指向任何地方。

空指針和 0

根據語言定義, 在指針上下文中的常數 0 會在編譯時轉換為空指針。

具體如下:

------------------------------------------------------------------------------------

可以使用未加修飾的0                  需要顯示的類型轉換

初始化                               函數調用, 作用域内無原型

指派                                 變參函數調用中的可變參數

比較

固定參數的函數調用且在作用域

内有原型

char *p = 0;                         execl("/bin/sh", "sh", "-c", "date", (char *)0);

if(p != 0)

-------------------------------------------------------------------------------------

注意:

if(p) 等價于 if(p != 0)。

這是一個比較上下文, 是以編譯器可以看出 0 實際上是一個空指針常數, 并使用正确的空指針值。這裡沒有任何欺騙; 編譯器就是這樣工作的, 并為、二者生成完全一樣的代碼。

--*空指針的内部表達無關緊要。*--

NULL和空指針

作為一種風格, 很多人不願意在程式中到處出現未加修飾的 0。是以定義了預處理宏 NULL (在 <stdio.h> 和其它幾個頭檔案中) 為空指針常數, 通常是 0 或者((void *)0) 。希望差別整數 0 和空指針 0 的人可以在需要空指針的地方使用NULL。

--*使用NULL隻是一種風格習慣;*-- 

預處理器把所有的NULL都還原回0, 而編譯還是依照上文的描述處理指針上下文的 0。特别是, 在函數調用的參數裡, NULL之前 (正如在 0 之前) 的類型轉換還是需要。C 程式員應該明白, 在指針上下文中 NULL 和 0 是完全等價的, 而未加修飾的 0 也完全可以接受。

--*任何使用 NULL (跟 0 相對) 的地方都應該看作一種溫和的提示, 是在使用指針。*--

程式員 (和編譯器都) 不能依靠它來差別指針0和整數 0。特别是, 不能在需要 ASCII 空字元 (NUL) 的地方用NULL。如果有必要, 提供你自己的定義#define NUL ’\0’。

=======================================================================================

空指針的迷霧:

空指針的内部 (或運作期) 表達形式, 這可能并不是全零, 而且對不用的指針類型可能不一樣。真正的值隻有編譯器開發者才關心。C程式的作者永遠看不到它們。

理清楚幾個概念

1,空指針,參見開頭的定義,不同機器對于空指針的定義可能不同。

2,空指針常數,0 ,這個常數由編譯器在運作階段根據處理指針的上下文來轉換為實際機器的空指針表達;

3,NULL宏,它隻是空指針常熟的一種風格的定義,有好的提示使用的是指針。

4,ASCII空字元(NUL), 它的确是全零, 但它和空指針除了在名稱上以外, 沒有任何必然關系。

5,“空串” (null string), 它是内容為空的字元串 ("")。在 C 中使用空串這個術語可能令人困惑, 因為空串包括空字元 (’\0’),但不包括空指針。

沖出迷霧:

沖出這些迷惘的一個好辦法是想象 C 使用一個關鍵字作為空指針常數。編譯器要麼在源代碼沒有歧義的時候把空指針常數轉成适當類型的空指針, 或者有歧義的時候發出提示。C 語言的空指針常數

關鍵字是“0”, 這在多數情況下都能正常工作, 除了一個未加修飾的“0” 用在非指針上下文的時候, 編譯器把它生成整數 0 而不是發出錯誤資訊, 如果那個未加修飾的0是應該是空指針常數, 那麼生成的程式不行。

簡單的方法:

1. 當你在源碼中需要空指針常數時, 用“0” 或“NULL”。

2. 如果在函數調用中 “0” 或 “NULL” 用作參數, 把它轉換成被調函數需要的指

針類型(實際上這個2條件有點過于苛刻)