close

在進入這階段時,請先確定前八個階段都確定會了再下來會好些。另外,有篇文章請先看過...

[console] 一維陣列與指標
[console] 二維陣列基本介紹
[console] 二維陣列與指標

在介紹完一維陣列的動態配置之後,接下來探討更常用的使用指標配置二維動態陣列。這種方式和配置一維陣列非常像,假設我們要配置一個 2*4 的矩陣,

其矩陣內容如下:

 

COL1

COL2

COL3

COL4

ROW1

0

1

2

3

ROW2

4

5

6

7

 

我們於08_使用指標建立一維動態陣列時有提到,C語言配置動態陣列的語法:

資料型態 *ptr;
ptr = (資料型態*)malloc(sizeof(資料型態)*cnt);

而今天我們要配置的是二維陣列,所使用到的指標是二次指標,也就是 int**,說白了,就是指標的指標。現在,在上列的語法中,我們把資料型態全都以int * 代替,ptr ptr2取代(因為是二維,變數方便辨識),至於cnt 先用 ROW代替。變成了下面這樣:

int  **ptr2;
ptr2 = (int**)malloc(sizeof(int*)*ROW);

沒錯!這就是二維動態陣列配置的第一步,它的實際意思就是:配置了ROW個整數指標陣列(現在知道指標陣列是拿來幹嘛的了吧!就是要拿來再生成其它的動態陣列)。接下來,我們再利用每個指標陣列(ROW)再去生成COL個整數陣列,所以所得到的二維陣列大小剛好就是 ROW * COL

for(int i=0; i< ROW; i++) ptr2[i] = (int*)malloc(sizeof(int)*COL);

接下來的動作,就和存取一般的二維陣列沒什麼二樣了。要特別注意的是,記憶體釋放要釋放完整!由於我們是先配置了ROW 個指標陣列,再配置整數陣列,所以我們要先釋放每個指標陣列(ptr2[i])後,再釋放二次指標(ptr2)。範例如下所示。

1. 原始碼 - C

// ====================================
// FileName: Ptr2Dim_C.cpp
// Author  : Edison.Shih.
// Complier: VC 2008

#include <stdio.h>
#include <stdlib.h>

#define ROW               2
#define COL                4

// ====================================
// main function
int main(int argc, char**argv)
{       
        int i=0, j=0;
        int **ptr2 = NULL;

        // 生成一維指標陣列
        ptr2 = (int**)malloc(sizeof(int*)*ROW);

        // 每個指標陣列再生成整數陣列
        for(i=0; i<ROW; i++) ptr2[i] = (int*)malloc(sizeof(int)*COL);

        // write
        int cnt = 0;
        for(i=0; i<ROW; i++) {
                for(j=0; j<COL; j++) ptr2[i][j] = cnt++;
        }

        // read value and address
        for(i=0; i<ROW; i++) {
                for(j=0; j<COL; j++) printf("ptr2[%d][%d]=%d(%0X)\n", i, j, ptr2[i][j], &ptr2[i][j]);
        }

        // 釋放指標陣列
        for(i=0; i<ROW; i++) free(ptr2[i]);

        // 釋放指標
        free(ptr2);

        return 0;
}

2. 原始碼 - C++

// ====================================
// FileName: Ptr2Dim_Plus.cpp
// Author  : Edison.Shih.
// Complier: VC 2008

#include <iostream>
using namespace std;

#define ROW                2
#define COL                4

// ====================================
// main function
int main(int argc, char**argv)
{       
        int i=0, j=0;
        int **ptr2 = NULL;

        // 生成一維指標陣列
        ptr2 = new int*[ROW];

        // 每個指標陣列再生成整數陣列
        for(i=0; i<ROW; i++) ptr2[i] = new int[COL];

        // write
        int cnt = 0;
        for(i=0; i<ROW; i++) {
                for(j=0; j<COL; j++) ptr2[i][j] = cnt++;
        }

        // read value and address
        for(i=0; i<ROW; i++) {
                for(j=0; j<COL; j++) {
                        cout << "ptr2[" << i << "][" << j<< "]=" << ptr2[i][j];
                        cout << "(" << hex << &ptr2[i][j] << ")" << endl;
                }
        }

        // 釋放指標陣列
         for(i=0; i<ROW; i++) delete ptr2[i];

        // 釋放指標
        delete ptr2;

        // 事實上, 上面那二行用 delete [] ptr2; 就行了

        return 0;
}

3. 執行結果

ptr2[0][0]=0(384430)
ptr2[0][1]=1(384434)
ptr2[0][2]=2(384438)
ptr2[0][3]=3(38443C)
ptr2[1][0]=4(384470)
ptr2[1][1]=5(384474)
ptr2[1][2]=6(384478)
ptr2[1][3]=7(38447C)

請注意,執行結果中,雖然是二維指標陣列,但是所配置的記憶體空間卻是連續的。

4. Memory leak問題:8_使用指標建立一維動態陣列時有提到,如果配置了記憶體空間沒有釋放完全,將造成程式所吃的記憶體會愈來愈多,最後將因資源潰乏導致程式無法順利結束,這種問題便稱為 memory leak。一般而言,memory leak是因為記憶體空間沒有進行釋放或釋放不完全引起的,而且除錯階段也不好抓,更是一般設計者的困擾。(由於我找不到memory leak 適當的中文,所以並沒有進行中文的翻譯。)

5. 記憶體碎片化(memory fragment)問題:上例的方式,當我們的 ROW COL 過大時,將會使得記憶體位址不連續,這個問題會使得到時存取陣列時,速度將變慢。關於避免記憶體碎片化問題有點艱澀,在這裡避開暫不討論。

 

 

arrow
arrow
    全站熱搜

    Edison 發表在 痞客邦 留言(5) 人氣()