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

Memory 使用1个malloc调用为2d矩阵分配内存,memory,runtime,malloc,free,Memory,Runtime,Malloc,Free,a=malloc(sizeof(int*)*5)//分配5个指针 每个指针指向一个包含5个整数的数组 foo(int **m) { ... } +---------+---------+---------+---------+ | m[0][0] | m[0][1] | m[0][2] | m[0][3] | +---------+---------+---------+---------+ | m[1][0] | m[1][1] | m[1][2] | m[1]

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

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
我们如何才能成功释放分配的内存? 使用free(a)会产生运行时错误

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
使用 对于(i=0;i编辑:整个故事

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
以前我忽略了分配2d数组的三种方法

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
动态2d数组方法1:

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
如果您知道编译时的列数,那么这个方法是有效的

We can allocate memory for 2d matrix using 1 malloc call as
int (*a)[5];
int i,j;
foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
+----+        +----+----+----+----+----+      
|m[0]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[1]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[2]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[3]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
这是因为m被声明为指向CCOLS int数组的指针。编译器知道它的大小并为您计算。m[iRow]=一个CCOLS int数组

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
您只能将其传递给具有此签名的函数:

#define CCOLS 200

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

...

free(m);
foo(int m[][CCOLS]) { ... }
foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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 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 (*m)[CCOLS]) { ... }
foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
不是这个签名:

#define CCOLS 200

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

...

free(m);
foo(int m[][CCOLS]) { ... }
foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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 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 **m) { ... }
+---------+---------+---------+---------+     
| 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[][CCOLS]如下所示:

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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如下所示:

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
动态2d数组方法2(并非所有编译器都支持C99):

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
这一个与前一个相同,但您不需要在编译时知道维度

We can allocate memory for 2d matrix using 1 malloc call as
int (*a)[5];
int i,j;
foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
+----+        +----+----+----+----+----+      
|m[0]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[1]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[2]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[3]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
您只能将其传递给具有此签名的函数:

#define CCOLS 200

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

...

free(m);
foo(int m[][CCOLS]) { ... }
foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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 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 **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
foo(int cCols, m[][cCols])  {}
如果您使用gcc,这里有更多

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
使用堆栈的动态2d数组方法3!(并非所有编译器都支持C99):

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
如果您对堆栈上的2d数组没有问题,这可以让您完全避免malloc

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
foo(int cRows, int cCols, m[cRows][cCols])  {}
我想你也可以这样声明一个全局变量

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
将其传递给函数的方式与方法2相同

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
动态2d数组方法4:

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
这是很多人使用的指针数组方法

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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] |     
+---------+---------+---------+---------+     
您使用一个malloc进行分配以提高效率。当然,然后您只使用一个free。只有当您有巨大的数组,其中连续内存变为并发出时,您才会希望对每一行分别进行malloc

foo(int **m) { ... }
+---------+---------+---------+---------+     
| 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 cRows, cCols;
... set cRows, cCols somehow ...
int m[cRows][cCols];
m[iRow][iCol] = n; 
int-cCols=10,cRows=100,iRow;
//分配:
//cCols*cRows*sizeof(int)=数据的空间
//cRows*sizeof(int*)=行PTR的空间
int**m=malloc(cCols*cRows*sizeof(int)+cRows*sizeof(int*);
//现在连接行指针。它们取第一个cRows*sizeof(int*)
//因为这正是m[row]所期望的。
//我们希望每个行指针都有自己的cCols大小的整数数组。
//为此,我们将使用行指针后的空格。
//计算行指针后面的空格所在位置的一种方法是
//取第n+1元素的地址:&m[cRows]。
//要获得行ptr,将&m[cRows]转换为int*,并将iRow*cCols添加到其中。
对于(iRow=0;iRow
a=malloc(sizeof(int*)*5);
实际上为int指针的5个元素数组分配内存,而
int(*a)[5]
表示指向5个int数组的指针。int*m=malloc(cxcysizeof(int)+cysizeof(int*);在这一行中,第二个术语应该是cxsizeof(int),如果您正在制作行指针。因此,行指针将是100个元素中的10个。如果是,请更正wrong@Luv:这不是我第一次遇到bug……我认为这是正确的,因为cy是行的#。因此需要需要需要cysizeof(int)的cy行指针字节。我将对代码进行注释,以明确“y”是行计数器,cy是行计数。