C語言Plus 2020-04-02
C語言指針
程式有問題時不要擔心。如果所有東西都沒問題,你就失業了
沒學指針就是沒學C語言!指針是C語言的精華,也是C語言的難點,破解C語言指針,會讓你的C語言水準突飛猛進。正如您所知道的,每一個變量都有一個記憶體位置,每一個記憶體位置都定義了可使用連字号(&)運算符通路的位址,它表示了在記憶體中的一個位址。請看下面的執行個體,它将輸出定義的變量位址:
#include <stdio.h>int main(){ int var1; char var2[10]; printf("var1 變量的位址:%p\n", &var1); printf("var2 變量的位址:%p\n", &var2); getchar(); return 0;}
當上面的代碼被編譯和執行時,它會産生下列結果:
實際上每次編譯運作的結果都會不一樣,因為記憶體是随機配置設定的。
通過上面的執行個體,我們了解了什麼是記憶體位址以及如何通路它。接下來讓我們看看什麼是指針。
什麼是指針?
所謂指針,也就是記憶體的位址;所謂指針變量,也就是儲存了記憶體位址的變量。不過,人們往往不會區分兩者的概念,而是混淆在一起使用,在必要的情況下,大家也要注意區分。就像其他變量一樣,您必須在使用指針存儲其他變量位址之前,對其進行聲明。指針變量聲明的一般形式為:
type *var-name;
在這裡,type 是指針的基類型,它必須是一個有效的 C 資料類型,var-name 是指針變量的名稱。用來聲明指針的星号 * 與乘法中使用的星号是相同的。但是,在這個語句中,星号是用來指定一個變量是指針。以下是有效的指針聲明:
int *ip; /* 一個整型的指針 */ double *dp; /* 一個 double 型的指針 */ float *fp; /* 一個浮點型的指針 */ char *ch; /* 一個字元型的指針 */
所有實際資料類型,不管是整型、浮點型、字元型,還是其他的資料類型,對應指針的值的類型都是一樣的,都是一個代表記憶體位址的長的十六進制數。
不同資料類型的指針之間唯一的不同是,指針所指向的變量或常量的資料類型不同。
如何使用指針
使用指針時會頻繁進行以下幾個操作:定義一個指針變量、把變量位址指派給指針、通路指針變量中可用位址的值。下面的執行個體涉及到了這些操作:
int main() { int var = 20; /* 普通變量的聲明 */ int *point; /* 指針變量的聲明 */ point = &var; /* 把變量var的位址指派給指針變量point */ printf("&var value: %p\n", &var); /* 在指針變量中存儲的位址 */ printf("point value: %p\n", point); printf("var value: %d\n", var); /* 使用指針通路值 */ printf("*point value: %d\n", *point); getchar(); return 0;}
可以看出通過指針可以修改變量的值,實際上指針是直接對記憶體進行操作,指針存在的最大意義是間接指派,
C語言中的空指針
在變量聲明的時候,如果沒有确切的位址可以指派,為指針變量賦一個 NULL 值是一個良好的程式設計習慣。賦為 NULL 值的指針被稱為空指針。
NULL 指針是一個定義在标準庫中的值為零的常量。請看下面的程式:
int main() { int *ptr = NULL; printf("ptr 的位址是 %p\n", ptr); return 0;}
#define NULL((void*)0)NULL是一個宏定義,是把0強轉為空指針。在大多數的作業系統上,程式不允許通路位址為 0 的記憶體,因為該記憶體是作業系統大哥的。然而,記憶體位址 0 有特别重要的意義,它表明該指針不指向一個可通路的記憶體位置。但按照慣例,如果指針包含空值(零值),則假定它不指向任何東西。
如需檢查一個空指針,您可以使用 if 語句,如下所示:
#include <stdio.h>int main() { int xxoo = 666; int *ptr = NULL; printf("ptr 的位址是 %p\n", ptr); for (int i = 0; i < 2; i++) { if (ptr == NULL) /* 如果 p 為空,則指派 */ { ptr = &xxoo; } if (ptr != NULL) /* 如果 p 非空,則修改内容*/ { *ptr = 'A'; } } printf("xxoo:%d\n", xxoo); getchar(); return 0;}
大家自己測試下,很有意思~
注意
C語言用變量來存儲資料,用函數來定義一段可以重複使用的代碼,它們最終都要放到記憶體中才能供 CPU 使用。