2
We can allocate memory for 2d matrix using 1 malloc call as
int (*a)[5];
int i,j;

a = malloc(sizeof(int *)* 5); // 5つのポインタを割り当て、各ポインタは5つのintの配列を指します

割り当てられたこのメモリをどのように解放できますか?free(a)を使用すると、実行時エラーが発生します

for(i = 0; i <5; i ++)free(a [i]);を使用する

free(a);

これにより、実行時エラーも発生します

4

1 に答える 1

10

編集:全話。

以前は、2D配列を割り当てる他の3つの方法無視していました。

動的2D配列法1:

これは、コンパイル時の列数がわかっている場合に機能します。

#define CCOLS 200

int (*m)[CCOLS] = malloc(cRows * sizeof(*m));
m[iRow][iCol] = n; // sets the item at iRow*CCOLS + iCol

...

free(m);

これは、mがCCOLSintの配列へのポインターとして宣言されているために機能します。コンパイラはそのサイズを認識しており、計算を行います。m [iRow]=CCOLSintの配列。

これは、次のシグネチャを持つ関数にのみ渡すことができます。

foo(int (*m)[CCOLS]) { ... }

コンパイラと使用するスイッチによっては、この署名が必要になる場合があります。

foo(int m[][CCOLS]) { ... }

この署名ではありません:

foo(int **m) { ... }

メモリのレイアウトとサイズが異なるため。

int m [] [CCOLS]は次のようになります:

+---------+---------+---------+---------+     
| m[0][0] | m[0][1] | m[0][2] | m[0][3] |     
+---------+---------+---------+---------+     
| m[1][0] | m[1][1] | m[1][2] | m[1][3] |     
+---------+---------+---------+---------+     
| m[2][0] | m[2][1] | m[2][2] | m[2][3] |     
+---------+---------+---------+---------+     
| m[3][0] | m[3][1] | m[3][2] | m[3][3] |     
+---------+---------+---------+---------+     

int ** mは次のようになります:

+----+        +----+----+----+----+----+      
|m[0]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[1]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[2]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[3]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      

動的2D配列メソッド2(すべてのコンパイラでサポートされているわけではないC99):

これは前のものと同じですが、コンパイル時にディメンションを知る必要はありません。

int cCols, cRows, iCol, iRow;
... set cRows, cCols somehow, they could be passed in as parameters also ...
int (*m)[cCols] = malloc(cRows * sizeof(*m));
m[iRow][iCol] = n; // sets the item at iRow*cCols + iCol

...

free(m);

これは、次のシグネチャを持つ関数にのみ渡すことができます。

foo(int cCols, m[][cCols])  {}

またはこれ

foo(int cRows, int cCols, m[cRows][cCols])  {}

gccを使用している場合は、ここに詳細があります。

STACKを使用した動的2D配列メソッド3!(すべてのコンパイラでサポートされているわけではないC99):

これにより、スタック上の2D配列に問題がない場合は、mallocを完全に回避できます。

int cRows, cCols;
... set cRows, cCols somehow ...
int m[cRows][cCols];
m[iRow][iCol] = n; 

この方法でもグローバル変数を宣言できると思います。

これをメソッド2と同じ方法で関数に渡します。

動的2D配列法4:

これは、多くの人が使用するポインタの配列メソッドです。

効率的に割り当てるために1つのmallocを使用します。そしてもちろん、無料で使用できるのは1つだけです。連続したメモリが発生して発行される巨大な配列がある場合にのみ、各行を個別にmallocする必要があります。

int cCols = 10, cRows = 100, iRow;

// allocate:
// cCols*cRows*sizeof(int) = space for the data
// cRows*sizeof(int*) = space for the row ptrs
int **m = malloc(cCols*cRows*sizeof(int) + cRows*sizeof(int*));

// Now wire up the row pointers.  They take the first cRows*sizeof(int*) 
// part of the mem becasue that is what m[row] expects.
// we want each row pointer to have its own cCols sized array of ints.
// We will use the space after the row pointers for this.
// One way to calc where the space after the row pointers lies is to
// take the address of the nth + 1 element: &m[cRows].
// To get a row ptr, cast &m[cRows] as an int*, and add iRow*cCols to that.
for (iRow = 0; iRow < cRows; ++iRow)
    m[iRow] = (int*)&m[cRows] + iRow*cCols; 

// or 
for (p=(int*)&m[cRows] ; iRow = 0; iRow < cRows; ++iRow, p+=cCols)
    m[iRow] = p; 


// use it:
...
m[iRow][iCol] = 10;
...

// free it
free(m);
于 2012-06-01T08:56:58.647 に答える