使用1 malloc调用为2d矩阵分配内存

Luv*_*Luv 2 memory malloc free runtime

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

a = malloc(sizeof(int*)*5); //分配5个指针,每个指针指向5个整数的数组

我们怎样才能释放成功分配的内存?使用free(a)会产生运行时错误

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

免费的(a);

这也会产生运行时错误

joh*_*ash 10

编辑:整个故事.

以前我忽略了三种其他分配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);
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为m被声明为指向CCOLS int数组的指针.编译器知道它的大小并为你做数学运算.m [iRow] = CCOLS整数数组.

您只能将此传递给具有此签名的函数:

foo(int (*m)[CCOLS]) { ... }
Run Code Online (Sandbox Code Playgroud)

也许这个签名,取决于您使用的编译器和开关:

foo(int m[][CCOLS]) { ... }
Run Code Online (Sandbox Code Playgroud)

不是这个签名:

foo(int **m) { ... }
Run Code Online (Sandbox Code Playgroud)

由于内存布局和大小不同.

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] |     
+---------+---------+---------+---------+     
Run Code Online (Sandbox Code Playgroud)

int**m看起来像这样:

+----+        +----+----+----+----+----+      
|m[0]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[1]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[2]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[3]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
Run Code Online (Sandbox Code Playgroud)

动态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);
Run Code Online (Sandbox Code Playgroud)

您只能将此传递给具有此签名的函数:

foo(int cCols, m[][cCols])  {}
Run Code Online (Sandbox Code Playgroud)

或者这个

foo(int cRows, int cCols, m[cRows][cCols])  {}
Run Code Online (Sandbox Code Playgroud)

如果你使用gcc,这里有更多信息.

动态二维数组方法3使用STACK!(所有编译器都不支持的C99):

如果你对堆栈上的2d数组没问题,这可以让你完全避免malloc.

int cRows, cCols;
... set cRows, cCols somehow ...
int m[cRows][cCols];
m[iRow][iCol] = n; 
Run Code Online (Sandbox Code Playgroud)

我假设你也可以用这种方式声明一个全局变量.

您将此方法传递给函数的方法与方法2相同.

动态二维数组方法4:

这是许多人使用的指针数组方法.

您使用一个malloc进行分配以提高效率.当然,你只使用一个免费的.只有当你有连续内存成为问题的巨大阵列时,你才想要单独地对每行进行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);
Run Code Online (Sandbox Code Playgroud)