我想知道,为什么这能工作
// read n as matrix dimension, then:
int* M;
M = (int*)malloc(n * n * sizeof(int));
// cycle through each "cell" in the matrix and read a number with
scanf("%d", &M[i * n + j]);
这不行吗?
// read n as matrix dimension, then:
int** M;
M = malloc(n * n * sizeof(int));
// cycle through each "cell" in the matrix and read a number with
scanf ("%d", &M[i][j]);
我只是不明白。在这两种情况下,它们都应该是双指针,对吗?
int **
应该指向一个int*
。在这里,您分配了一些内存 - 准确地说是sizeof(int)*rows*cols
字节,然后使用M[i]
等。这里基本上M[i]
*(M+i)
我们将访问malloc
返回的一个地址的偏移量i*sizeof(int*)
但您分配给rows*cols
int
而不是int*
-s - 因此您最终将访问您不应该访问的内存(通常在sizeof(int*) > sizeof(int)
的系统上),这将导致您出现未定义的行为。
那么解决方案是什么呢?很好地分配int*
-s。
int ** M = malloc(sizeof *M * rows);
if(!M){
perror("malloc");
exit(EXIT_FAILURE);
}
for(size_t i = 0; i < rows; i++){
M[i] = malloc(sizeof *M[i] * cols);
if(!M[i]){
perror("malloc");
exit(EXIT_FAILURE);
}
}
对于您的情况rows = N
和cols = N
.
这将给你一个锯齿状的数组,你可以像以前一样访问它。malloc
随之而来的是检查它的返回类型并在完成使用它时释放内存的责任。这样做。
在第一种情况下,您正在访问分配的内存块,并且您已经使用索引i
和j
实现了内存访问,以使自己能够像在 2D 数组中那样访问内存。所以在这里使用双指针是没有意义的。你的所作所为是合法的。
在这两种情况下,它们都应该是双指针
不,他们不应该是。第一个与第二个不同。无论如何,它们都没有表示同样的事情。
案例 1 :-
int* M;
M = (int*)malloc(n * n * sizeof(int));
这里为单指针M
分配内存。假设您要将5
整数存储到该内存中。所以它看起来像
-------------------------------
| 10 | 20 | 30 | 40 | 50 |
-------------------------------
M M[0] M[1] M[2] m[3] M[4] <--- Its a 1D array, only one row of 5 int
案例 2 :-
int **M;
M = malloc(n * n * sizeof(int));
M[0][0] M[0][1]
| | | | ....... | | <---- If below one is not done then how will you store the numbers into these
----------- ----- ---------
| | | |
M[0] M[1] M[2] .... M[4] <--- didn't allocated memory for these rows or 1D array
| | | |
-----------------------------------
|
M <---- allocated memory for this
它不起作用,因为M
是双指针,并且您仅为M
分配了内存,您没有为M[row]
分配内存。 这就是为什么下面的语句不起作用的原因。
scanf ("%d", &M[i][j]);
所以要先让它工作 像你一样为M
分配内存
M = malloc(row*sizeof(*M)); /* row indicates no of rows */
然后为每一行分配
for(int index = 0 ;index < row;index++) {
M[index] = malloc(col * sizeof(*M[index])); /* col indicates number of columns */
}
并扫描矩阵输入
for(int index = 0 ;index < row;index++) {
for(int sub_index = 0 ;sub_index < col; sub_index++)
scanf("%d",&M[index][sub_index]);
}
一旦完成矩阵的工作,就会使用每行的free()
释放动态分配的内存,以避免内存泄漏。
其他答案(建议一个malloc
用于M
,n
malloc
s表示行)是正确的,但不是分配矩阵的最有效方法。但是,您可以只用一个malloc
调用来分配矩阵,同时仍然允许您使用M[i][j]
按行和列对其进行索引,如下所示:
int (*M)[cols] = malloc(rows * sizeof *M);
这将M
声明为指向长度为cols
的int
数组的指针,并请求malloc
分配此类数组的数量rows
这意味着您将获得一个rows * cols
int
s (sizeof *M == sizeof(int) * cols
的单个块)。
当malloc
成功时,您可以使用M
,就好像它被声明为int M[rows][cols]
一样,以便您可以使用
scanf("%d", &M[i][j]);
它看起来更复杂,但M
分配为一个连续的内存块,这允许处理器优化对它的访问。
作为额外的奖励,您还可以通过一次通话将其释放:
free(M);
这确实需要 C99 支持,或者至少支持可变长度数组,但矩阵本身不是适当的可变长度数组。它仍然由malloc
分配,但M
的声明允许您像使用它一样使用它。