Pointer - 2D Array


現在實做上我們需要一個 int array, size 為 2x3

動態二維的做法如下

int ** dp[2] = (int **) malloc(sizeof(int*)*2);

 int i = 0;
 for (i = 0; i < 2; ++i)
 {
    dp[i] = (int*)  malloc(sizeof(int)*3);
 }

在使用上就是 dp[i][j] 之類的使用。 dp 的型態為 int**

這先放著,看另外一種做法,就是直接宣告 int sp[2][3]

請問這兩個在型態上有何差異?

要了解這個,我們要先了解兩樣東西

  1. 指標陣列 (意即陣列中的元素都是指標)
  2. 指向陣列的指標(意即一個指標變數指向一個陣列)

指標陣列


給一個指標陣列的例子 -

int a1, a2;

int * pa[3];

pa[0] = &a1;
pa[1] = &a2;
pa[2] = NULL;

也就是 pa[i] 的型態應為 int* 。這也是動態二維陣列可以使用的原因。

pa[i] 既然是一個 int* 那是否可以他是一個陣列? 答案是肯定的。

甚至我們也可以造出 "三角形" 的陣列 ( pa[i] 所指的陣列長度遞減或遞增)

陣列指標


先給 code

int a[16];
int *pa = a;

觀察前後文,如果要解釋 pa 的邏輯意義,也許我們會說,pa 是一個陣列,或者指向一個陣列a

而我們用更精確的文字來描述的話,也許可以說 pa 是一個指向 array a 第 0 個元素的指標。

這邊並非要去玩文字遊戲,是因為我們要把所謂 "指向陣列" 這句話解釋得更清楚。

--

那說到此,所謂"指向陣列的指標"到底是什麼?

先問一個問題,為何我們要在意指標的型態?不太清楚的人可以參考 Point-type

簡單而言,一個指標的型態,決定了一件很重要的事情,就是他所指向的物件的 size 是多少。

也就是說,假設 p 是一個指向 type T 的指標,那這樣 sizeof(*p)應該要等於 sizeof(T)

--
我們用這樣的論述回到陣列指標,假設有個陣列 int a[16]。在 sizeof(int) == 4 的情況下, sizeof(a) 應為 16 * 4 = 64. 若有個指標 p 可以被稱為 "指向這個陣列a的指標" 那 sizeof(*p) 就應為 64。

但是我們可以見到的是,在先前的 code 中, *pa 的型態為 int,因此 sizeof(*pa)4。這也就是 *pa 無法被稱作指向 a 的指標的原因。

我們先給出正確的語法

int a[16];
int (*p)[16] = &a;

稍微仔細一點說明上面的語法。記得兩個東西唯一決定一個陣列: size and type。 因此我們在描述一個陣列時,比較精確的描述會是: "a 是一個 size 為 16 的整數陣列"。
p 是一個指標,指向一個 size 為 16 的整數陣列。

這邊讀者可以做一個實驗,去看看 pp+1 差多少。 答案應為 sizeof(int) * 16

--

理解了上面這些敘述,我們可以回到原本的 2D-array。
我們來試著解釋 int a[10][20] 從陣列指標的角度來看是什麼東西。

int a[10][20];
int (*p)[20] = a; //合法

事實上 a 的型態就如上面的 code 所言,等同於 p : 一個指向 size 20 的整數陣列。
記得 p 本身是一個指標變數,也就是說 p+1 會與 p 差一個 *p 的大小(不太懂這句話的可以先把 p 當作 int*想)。
因此如果我們有10個 *p 的大小,就可以讓 p, p+1, ... p+9 都個別指向一個 size 為 20 的整數陣列,而造出一個2D陣列。

結論


這兩者各有優劣,而在決定使用哪一種後,function 的 prototype也隨之固定。初學者往往會將兩者混為一談或者誤用,因此須了解以上觀念避免coding時造成編譯不通過或是記憶體錯誤的問題。

results matching ""

    No results matching ""