在c語言中,指標的重要性不言而喻,但在很多時候指標又被認為是一把雙刃劍。一方面,指標是構建資料結構和操作記憶體的精確而高效的工具。另一方面,它們又很容易誤用,從而產生不可預知的軟體bug。下面總結一下指標使用的常見錯誤。
int *p; //或者 int *p = null;
···*p = 10; //錯誤,指標未初始化
上述程式將值10寫到未知的記憶體位置,如果p指向系統記憶體空間,這樣很可能把系統本來位址裡的內容給覆蓋了,會導致程式或者系統的崩潰。
在堆中開闢記憶體以後,使用完成必須釋放記憶體,否則會造成記憶體洩漏,示例如下:
int *p = (int *)malloc(100);
···free(p);
p = null;
很多時候使用指標開闢了記憶體空間,然後如果對指標指向進行改變操作,操作完成後直接釋放記憶體,會釋放了不該釋放的位置;另外程式丟失了對已開闢記憶體空間的控制,造成記憶體洩漏,示例如下:
//這種時候一般會定義兩個指向同乙個開闢的記憶體空間的指標變數,乙個用於操作,乙個用於釋放,避免造成記憶體洩漏
char *p = (char *)malloc(100);
strcpy(p, "abcdefg");
p += 1; //對指標指向進行改變操作
*p = 'a';
free(p);
p = null;
"野指標"不是null指標,是指向「垃圾」記憶體的指標。人們一般不會錯用null指標,因為用if語句很容易判斷。但是「野指標」是很危險的,if語句對它不起作用。「野指標」的成因主要有兩種:
第一種,指標變數沒有初始化。任何指標變數剛被建立時不會自動成為null指標,它的預設值是隨機的,它會亂指一氣。示例如下:
char *p; //錯誤,未初始化,成為野指標
第二種,指標變數被free或者delete之後,沒有置為null,讓人誤以為是個合法的指標。示例如下:
char *p = (char *)malloc(100);
...free(p); //錯誤,沒有置為null,成為野指標
如果函式的引數是乙個指標,不要指望用該指標去申請動態記憶體,示例如下:
#include #include #include void getmemory(char *p, int num)
int main()
上面getmemory(str, 200)
並沒有使pstr獲得期望的記憶體,pstr依舊是null,為什麼?
問題出在getmemory
函式中。編譯器總是要為函式的每個引數製作臨時副本,指標引數p的副本是_p,編譯器使_p = p。在本例中,_p申請了新的記憶體,只是把_p所指的記憶體位址改變了,但是p絲毫未變,仍然是空指標。事實上,每執行一次getmemory
函式就會洩漏一塊記憶體,因為沒有用free釋放記憶體。
指標引數申請記憶體的兩種正確用法
第一種用法:使用函式返回值來傳遞動態記憶體,示例如下:
#include #include #include char* getmemory(char *p, int num)
int main()
這裡強調不要用return語句返回指向」棧記憶體「的指標,因為」棧記憶體「指標在函式結束時已經被自動**。
第二種用法:使用指向指標的指標作為引數來傳遞動態記憶體,示例如下:
#include #include #include void getmemory(char **p, int num)
int main()
在需要修改指標變數本身的時候,需要使用指向指標的指標作為引數,這也是傳值與傳位址的差別所在。
參考:
深入理解c語言-指標使用的常見錯誤
深入理解C語言 深入理解指標
關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...
深入理解C語言 深入理解指標
關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...
C語言指標深入理解
前幾天看了乙個程式,裡面一段關於指標的 讓我非常糾結,看了很久才看懂,在這裡將將其記錄下來,希望能對大家有一定的幫助,先看示例程式 編譯器gcc include include include typedef struct list node list node,list,plist node st...