我在想,为什么会这样做
// 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]);
我只是不明白。在这两种情况下,它们应该是双指针,我是对的吗?
答案 0 :(得分:1)
int **
应该指向int*
。在这里你已经分配了一些内存 - 准确sizeof(int)*rows*cols
字节,然后你使用M[i]
等。M[i]
基本上是*(M+i)
我们将访问i*sizeof(int*)
偏移从malloc
返回的一个地址开始,但您为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 :(得分:0)
案例1: -
GET /documents/_search
{
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "somefield.field1"
}
},
]
"should": [
{
"exists": {
"field": "somefield"
}
}
],
"minimum_should_match": 2
}
}
}
这里为int* M;
M = (int*)malloc(n * n * sizeof(int));
分配内存,这是单指针。假设您要将M
个整数存储到该内存中。所以它看起来像
5
案例2: -
-------------------------------
| 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
它不起作用,因为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]);
}
每行动态分配的内存避免内存泄漏。
答案 2 :(得分:0)
其他答案(为行malloc
和M
n
建议一个malloc
是正确的,但不是分配矩阵的最有效方法。但是,您可以仅使用malloc
次调用分配矩阵,同时仍允许您按行{c} M[i][j]
对其进行索引,如下所示:
int (*M)[cols] = malloc(rows * sizeof *M);
这将M
声明为指向长度为int
的cols
数组的指针,并请求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
的声明允许您像使用它一样使用它。