什麼是指標(pointer)

值為變數、陣列元素、函式等所在記憶體位址的變數。C語言以 int *p 的方式宣告,以 &x 取出 x 的位址,以 *p 讀寫 p 所指向的值。指標加上整數時,會以所指向型別的大小為單位前進。陣列名稱在多數運算式中會轉換成指向第一個元素的指標,a[i] 與 *(a + i) 意義相同。表示不指向任何地方的值稱為 NULL 指標。

日文名稱: ポインタ

「指標(pointer)」出現在1領域的13道練習題中(C語言基礎等)。

這個名詞所屬的領域: C語言基礎

宣告與基本操作

int *p; 宣告了「指向 int 的指標」p。以 p = &x; 放入變數 x 的位址後,*p = 5; 就會把5寫入 x。函式的引數是傳值,若要在函式中改變呼叫端的變數,就把它的位址當作指標傳入。透過指向結構的指標使用成員時,(*p).m 可寫成 p->m。

指標運算與陣列

指向 int 的指標 p 加1時,位址不是前進1位元組,而是前進 sizeof(int) 位元組(許多環境為4位元組)。陣列名稱除了作為 sizeof 或 & 的對象等情況外,會轉換成指向第一個元素的指標。因此把陣列傳給函式時,實際上只傳了第一個元素的位址,在函式中用 sizeof 無法得知整個陣列的大小。

嵌入式中的用法與注意事項

在微控制器上,會像 (volatile uint32_t *)0x40020014 這樣把整數位址轉換成指標,來讀寫周邊電路的暫存器。透過未初始化的指標、NULL 指標,或指向已釋放區域的懸置指標進行讀寫是未定義行為,在沒有作業系統的環境中可能在不知不覺中破壞其他資料。

練習指標(pointer)的題目

int 為4位元組,指標為8位元組。指向 int 的指標 p 的值(位址)為 0x1000 時,p + 3 的值為下列何者?

  1. A0x100C
  2. B0x1012
  3. C0x1018
查看答案與解析

正確答案:A. 0x100C

指標加上整數時,會以所指向型別的大小為單位前進。int 為4位元組,因此 p + 3 指向 3 × 4 = 12 位元組之後,也就是 0x1000 + 0xC = 0x100C。p + 3 是陣列元素 p[3] 的位址,*(p + 3) 與 p[3] 意義相同。若是指向 char 的指標則每次前進1位元組,指向 double(8位元組)的指標則每次前進8位元組。

C語言中,參考 NULL 指標(p 為 NULL 時讀取 *p)時的說明,下列何者正確?

  1. A標準規定一定會被偵測為執行時錯誤,在任何環境中都會顯示錯誤訊息並停止程式
  2. BNULL 規定指向0號位址,因此在任何環境中都會讀出0號位址的內容並繼續處理
  3. C是未定義行為,在作業系統上一般會異常終止,但在沒有MMU的微控制器上可能讀得到0號位址而沒有察覺
查看答案與解析

正確答案:C. 是未定義行為,在作業系統上一般會異常終止,但在沒有MMU的微控制器上可能讀得到0號位址而沒有察覺

參考 NULL 指標是未定義行為,會發生什麼事標準並未規定。Linux 或 Windows 不會在0號位址附近配置頁面,因此參考時會發生分頁錯誤,程式一般會異常終止(例如 Linux 的區段錯誤)。在沒有MMU的小型微控制器上,0號位址可能有快閃記憶體或中斷向量表而能夠讀取,錯誤可能沒有表現出來就造成誤動作。使用指標前確認它不是 NULL 非常重要。

常見問題

指標的大小是多少?

在許多64位元環境中是8位元組,在32位元的微控制器上是4位元組。無論指向 char 還是 double,資料指標的大小一般相同。指標不一定與 int 一樣大,因此要把位址存入整數時,使用 stdint.h 的 uintptr_t。

const char *p 與 char *const p 有什麼不同?

const char *p 是「指向 const char 的指標」,不能透過 p 改寫字元,但 p 本身可以改指其他位址。char *const p 是「指標本身為 const」,p 不能改變,但所指向的內容可以改寫。可以這樣讀:const 在 * 的左邊時固定所指向的內容,在右邊時固定指標本身。

解析中的「指標(pointer)」

出現「指標(pointer)」的題目(13題)

  1. int 為4位元組,指標為8位元組。指向 int 的指標 p 的值(位址)為 0x1000 時,p + 3 的值為下列何者?
  2. int 為4位元組,指標為8位元組。執行上方程式時的輸出,下列何者正確?
  3. 關於上方函式 make 所回傳的指標,下列何者正確?
  4. C語言中,參考 NULL 指標(p 為 NULL 時讀取 *p)時的說明,下列何者正確?
  5. C語言的標準中,關於 int 型別的大小有何規定?下列何者正確?
  6. 執行上方程式時的輸出,下列何者正確?
  7. C語言中,(1) 在函式中沒有加 static 宣告的區域變數、(2) 以 malloc 配置的區域、(3) 在函式外宣告的變數,各自存在的期間(生命週期)的組合,下列何者正確?
  8. 在上方的宣告之後,寫入甲「p = t;」、乙「*p = 'x';」、丙「q = t;」、丁「*q = 'x';」其中之一。會發生編譯錯誤的組合為下列何者?
  9. 執行上方使用函式指標陣列的程式時的輸出,下列何者正確?
  10. C語言中,建議在 free(p); 之後立刻寫 p = NULL; 的理由,下列何者最適當?
  11. 微控制器的輸出暫存器以上方的方式宣告並使用。關於這個宣告的說明,下列何者正確?
  12. 關於C語言標準所說的未定義行為,下列說明何者正確?
  13. 以 gcc 啟用最佳化來編譯上方的函式時,if (p == NULL) 的判斷可能被刪除。其理由為下列何者?

相關名詞

未定義行為 陣列 變數 微控制器(MCU) 引數 堆疊 動態記憶體配置 懸置指標 回傳值 頁面錯誤

前往名詞解釋列表