0

指標動態產生陣列的兩三事

| 7/04/2012
星星,其實是指標

對大多數程式設計師而言,是能不用就不用的東西。其實先進的程式語言,幾乎都會把指標這種東西排除在外。最主要的原因不外乎就是它難以駕馭的問題;只要稍有疏失,就可能導致整個應用程式不穩定。其實今天這篇文章要談的不是該怎麼用指標的,而是使用指標分配二維陣列記憶體的問題。因為這個地方很容易產生一個嚴重的迷思。

相信大家都知道,用單一指標、再分配某個變數實質佔有空間的乘積之後,變成了如同陣列一般的區塊。

好比如說,我們希望有一個 int [5] 的空間,這裡就會用:

int *a = malloc(sizeof(int) * 5) 來宣告。

當然,不要忘記要釋放:free(a);

那,如果我希望有個 int [5][5] 的空間呢?
喔,不就是雙重指標嗎?
所以就是:

int **a = malloc (sizeof(int) * 5 * 5);

簡單嘛!

錯,而且錯很大,錯到你可能 de 不出 bug 在哪邊。
這也是很多人會犯下的錯誤。

我們把動作拆開來看第一項,當我們想要產生 int [5] 的時候
我們把 int *a 的星號拿掉,成了我們要產生的目標:int,所以我們用 malloc (sizeof(int) * count)。所以換到了雙重指標的時候,int **a 要產生的目標應該是:int *。然後才是 int * 要產生的目標:int。

所以程式碼應該是

int **a = malloc (sizeof(int *) * 5);

for ( int i = 0; i < 5; i++ )
     *(a + i) = malloc ( sizeof (int ) * 5 );

當然,如果你真的要這樣寫,到時候要 free 的時候會瘋掉,但也是保險的作法。為什麼?
因為我們把程式合併起來,整個程式碼是:

int **a = malloc (sizeof (int *) * 5 + sizeof (int) * 5 * 5)
請注意,這裡空間雖然分配了,可是你實際在使用的時候,因為要保證所有 int ** 底下的 int * 所指的位置,所以很容易指錯位置,所以上述的方法是比較保險的。

真複雜?沒錯,超級複雜的。
看完有沒有一堆星星在繞呢?