跳至內容

C/指針

本頁使用了標題或全文手工轉換
維基教科書,自由的教學讀本
< C

指標的定義

[編輯]
  • 指標為一種變數,儲存的內容是記憶體位址。
  • 指標的使用會因為目的型態不同而有些微的影響。

理解指針

[編輯]

指針是C語言中一個較難理解的概念,因為這個概念很接近底層。要想理解它,要從計算機底層開始。

計算機底層的存儲

[編輯]

在計算機內部有很多的存儲單元,每個存儲單元都可以存放數據。這些存儲單元就像一個個小盒子,每個盒子裡只能存放一個數字。

於是你看着眼前堆放的一大堆盒子,如何找到某個特定的盒子裡存放的數據呢?

我們可以把盒子整齊排成一排,按順序編號。這樣,我們只需要報出編號,就能順利找到一個盒子。

你可以想象,在計算機的虛擬世界中,有一個很高的柱子,這個柱子有很多層,每層都是一個格子,每個格子存放一個數字。這些格子按順序編號,每個格子都有唯一的編號,用這個編號就能找到對應的格子。

無論採用哪種比喻,本質上都是相同的。內存中有很多存儲單元,按順序編號,用編號定位。這個「編號」就是「內存地址」。這就是計算機內部的內存組織形式。

指針

[編輯]

所謂指針,無非是一類變量,這類變量存儲的值是存儲單元的地址,而不是通常的需要加工處理的數據(不過少數情況下也可能對指針進行運算)。你可以理解成:「指針」就是「」向一個存儲單元的「標」。

指針的類型

[編輯]

指針的類型,其實就是指針指向的存儲單元中的數據的類型。任何類型的數據,在計算機內部都不過是二進制形式的數字。存儲單元可沒有區分數據類型的能力。所以,為了方便使用、避免出錯,C語言的設計者讓指針擁有了類型,這樣就可以用指針的類型來區分目標存儲單元中的數據的類型。

不同類型的指針在使用時是有區別的。

現實中的計算機幾乎全部是按字節編址的,也就是每個小盒子裡都只能裝一字節(8 個二進制位)的數據。而在 C/基本數據類型 中講到,不同類型的數據會占用不同字節數的空間,如 int 占用 4 字節、long long 占用 8 字節。

當我們使用指針時,即操作指針指向的存儲單元的值時,實際上會連同這個目標存儲單元後面的幾個單元一起操作,具體的單元數量取決於指針的類型。比如,操作 int 型的指針指向的存儲單元,就會從目標地址開始,一同操作四個單元的數據;操作 long long 型的指針指向的存儲單元,就會一口氣操作 8 個單元的數據。

你可以理解成,我們認為這幾個連續的存儲單元中存放了某種類型的數據,於是我們定義了一個指針為這種類型,並讓它指向這段存儲單元的開頭。這樣,我們只需要操作這個指針,就可以很方便的操作這幾個連續存儲單元中存放的整個數據。


講完了理論,接下來該看看實踐了。

變數指標

[編輯]
  • 指標的宣告:

 int *ptr;  /* 則  (int *) 為變數型態,ptr 為變數名稱 */

  • 取得記憶體位址:在變數前面使用 '&' 字元。
  • 指向記憶體位址:在變數前面使用 '*' 字元。
#include <stdio.h>
int main()
{
    int v = 5;
    int *ptr = &v;
    printf("%d\n", *ptr);
}

函式指標

[編輯]

函式其實也可以是指標。

#include <stdio.h>
typedef void (*MyDelegate)(int i );
MyDelegate test1( int i ) 
{
    printf("%d\n", i );
}
MyDelegate test2( int i ) 
{
    printf("%d\n", i+1 );
}

int mainint argc, char* argv[]
{
    MyDelegate function;
    function = (MyDelegate)test1;
    function( 21 );  /* 等同於呼叫 test1 */
    function = (MyDelegate)test2;
    function( 21 );  /* 等同於呼叫 test2 */
}