
例如,我們宣告並指派初值 22 給整數變數 a ,編譯器將變數 a 放在 0110 的記憶體位址裡,稍後我們再宣告另一個指向 a 的指標變數 aPtr ,假設編譯器 aPtr 放在 1001 的記憶體位址裡,如下圖所示

因此,指標變數 aPtr 的內容為變數 a 的記憶體位址,如下

宣告 C 語言的指標變數,格式如下

* 為宣告指標所用的運算子,注意這跟乘法運算子一樣,編譯器會依上下文判斷星號用為宣告指標,還是用為兩數相乘。
很多情況下我們都需要直接操作記憶體位址,例如提升程式執行效率與建立資料結構。 C 語言中使用指標需要先經過宣告,如下列程式建立一個指標變數 aPtr 指向變數 a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <stdio.h> int main( void ) { int a = 9; int *aPtr; aPtr = &a; printf ( "利用指標指向變數 *aPtr = %d\n" , *aPtr); return 0; } /* 《程式語言教學誌》的範例程式 檔名:aPtr.c 功能:示範指標的宣告及使用 作者:張凱慶 時間:西元2010年4月 */ |
編譯後執行,如下

第 6 行
6 | int *aPtr; |
為宣告指標變數。第 7 行
7 | aPtr = &a; |
替指標變數指派初值,注意, & 為取址運算子,可以取得該變數的記憶體位址,這跟位元運算的且運算子是相同的,所以編譯器會依前後文自行判斷用途。
這兩行可以合併寫成
6 | int *aPtr = &a; |
第 9 行
6 | printf ( "利用指標指向變數 *aPtr = %d\n" , *aPtr); |
指標變數使用時另加上的星號,稱為間接運算子或反參考運算子,這是用來取得該指標所指向的數值,而非記憶體位址。
下列程式依次印出變數 a 的值與記憶體位址、 aPtr 的值與所參考的數值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <stdio.h> int main( void ) { int a = 9; int *aPtr = &a; printf ( "a = %d\n" , a); printf ( "&a = %p\n" , &a); printf ( "aPtr = %p\n" , aPtr); printf ( "*aPtr = %d\n" , *aPtr); return 0; } /* 《程式語言教學誌》的範例程式 檔名:aPtr2.c 功能:印出指標變數的記憶體位址 作者:張凱慶 時間:西元2010年4月 */ |
編譯後執行,如下

由於 C 語言的函數只能回傳一個值,所以當程式需要呼叫函數修改超過兩個值的時候,可以傳遞指標當作參數,讓呼叫的函數直接進行修改,如下例的函數 swap() 將 a 及 b 的值進行對調
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <stdio.h> void swap( int *, int *); int main( void ) { int a = 22; int b = 11; printf ( "兩數交換以前.. a = %d, b = %d\n" , a, b); swap(&a, &b); printf ( "兩數交換以後.. a = %d, b = %d\n" , a, b); return 0; } void swap( int *aPtr, int *bPtr) { int temp; temp = *aPtr; *aPtr = *bPtr; *bPtr = temp; } /* 《程式語言教學誌》的範例程式 檔名:swap.c 功能:示範利用指標修改兩個參數 作者:張凱慶 時間:西元2010年4月 */ |
編譯後執行,如下

第 12 行
12 | swap(&a, &b); |
將兩個變數取址後就是指標變數,然後傳遞給函數 swap()
19 20 21 22 23 24 25 26 | void swap( int *aPtr, int *bPtr) { int temp; temp = *aPtr; *aPtr = *bPtr; *bPtr = temp; } |
函數 swap() 接受兩個指標的參數後,另以一個區域變數 temp 暫存 aPtr 所指向的值,然後把 bPtr 的值給 aPtr ,注意此時兩個變數 aPtr 及 bPtr 的值一樣。最後把暫存變數 temp 的值,也就是 aPtr 原先所儲存的值給 bPtr ,兩數的值便做了對調。
由於陣列名稱就是指標,字串也就是字元陣列常常直接利用指標來操作,如下例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> int main( void ) { char *aPtr = "Seeing is believing." ; while (*aPtr != '.' ) { printf ( "%c\n" , *aPtr); aPtr++; } return 0; } /* 《程式語言教學誌》的範例程式 檔名:charPtr.c 功能:示範利用指標操作字元陣列 作者:張凱慶 時間:西元2010年4月 */ |
編譯後執行,如下

第 5 行
5 | char *aPtr = "Seeing is believing." ; |
指標變數 aPtr 會指向此字串第一個字元,也就是大寫 S 的記憶體位址。
第 7 到 10 行
7 8 9 10 | while (*aPtr != '.' ) { printf ( "%c\n" , *aPtr); aPtr++; } |
此即利用迴圈逐行印出每個字元。
這裡注意指標也是可以進行計算的,但有其限制,合法的指標運算如下表
相同資料型態的指標才可互相指派 |
指標可相加或相減某一範圍的整數 |
指向相同陣列的指標可以相減或比較 |
指標可以指派 0 或是與 0 做比較 |
6 則留言:
"指標是用來指向儲存指向某個記憶體位址的資料型態"<=這句話好像外星話一樣,拜託修改的白話些,畢竟這篇是連結到初學者文章的。
已把贅字刪除,感謝提醒 ^^
非常感謝^^,貴站的內容超充實,幾乎超越坊間所有的電腦書。站長人帥又用心,加油!
這兩行可以合併寫成
6 int *ptr = &a;
是不是應該改為
6 int *aPtr = &a;
這地方打錯字了,已修改,感謝指正 :)
內容清楚,很棒。
張貼留言