指標(pointer)是對資料物件或函數的一種參照。指標有多種用途,例如定義“傳址呼叫”函數,它還可以實現動態資料結構,例如連結串列和樹。
通常,管理大量資料的有效方法不是直接處理資料本身,而是使用指向資料的指標。例如,如果需要對大量的大型記錄進行排序,對指向該記錄的指標列表進行排序效率要比直接對記錄排序高得多,因為這樣無需在記憶體中移動資料。
類似地,如果需要把大型記錄傳入函數,傳遞指向該記錄的指標會比直接傳遞記錄本身更經濟,即使函數不需要修改該記錄。
指標代表了一個物件或函數的地址和型別。如果一個物件或函數具有 T 型別,那麼指向它的指標就具有一個衍生出的指向 T 的指標型別(pointer to T)。例如,如果 var 是一個 float 變數,那麼表示式 &var(其值是該 float 變數的地址)屬於指向 float 的指標型別,按照 C 語言表達,就是 float* 型別。
指向任何 T 型別的指標也被簡稱為
T 指標(T point)。因此,&var 中地址運算子會生成一個 float 指標。
因為 var 沒有在記憶體中移動位置,所以表示式 &var 是一個常數指標。然而,C 也允仵使用指標型別來定義變數。指標變數儲存的是另一個物件或函數的地址。我們後面會進一步討論指向陣列和函數的指標。首先,看看如何宣告指向非陣列物件的指標,語法如下:
型別 * [型別限定符列表] 名稱 [= 初始化器];
在宣告中,星號(*)表示“指向的指標”。識別符號“名稱”被宣告為一個物件,其物件型別為“型別”,也就是“指向‘型別’的指標”。型別限定符為可選擇項,可能包含 const、volatile 和 restrict 的任意組合。
下面是一個簡單的例子:
int *iPtr; // 宣告iPtr作為一個指向int的指標
int 型別是 iPtr 指標所指向的物件的型別。為了讓指標能夠參照到給定的物件,將該物件的地址賦值給該指標。例如,如果 iVar 是一個 int 變數,那麼下面的賦值操作會讓 iPtr 指向變數 iVar:
iPtr = &iVar; // 使得iPtr指向變數iVar
一般形式的宣告包含了用逗號分隔開的宣告符列表,每個宣告符宣告了各自的識別符號。在指標宣告中,星號(*)是宣告符的一部分。我們可以在一個宣告中同時定義和初始化變數 iVar 和 iPtr,如下所示:
int iVar = 77, *iPtr = &iVar; // 定義一個int變數,以及一個指向它的指標
這兩個宣告中的第二個宣告,將 iPtr 初始化為變數 iVar 的地址,這使得 iPtr 指向 iVar。圖 1 展示了變數 ivar 和 iPtr 在記憶體中可能的排列方式。這裡的地址為範例所需,純粹是虛構的。如圖 1 所示,儲存在指標 iPtr 中的值是物件 iVar 的地址。
圖 1