C - 动态矩阵分配:对我来说没有意义

时间:2018-02-15 18:22:59

标签: c pointers matrix dynamic allocation

我在想,为什么会这样做

// 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]);

我只是不明白。在这两种情况下,它们应该是双指针,我是对的吗?

3 个答案:

答案 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 = Ncols = N

这将为您提供一个锯齿状阵列,您可以像访问一样进行访问。使用malloc时,负责检查它的返回类型并在使用完后释放内存。那样做。

在第一种情况下,您正在访问已分配的内存块,并且您已使用索引ij实现了内存访问,以便在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)

其他答案(为行mallocM n建议一个malloc是正确的,但不是分配矩阵的最有效方法。但是,您可以仅使用malloc次调用分配矩阵,同时仍允许您按行{c} M[i][j]对其进行索引,如下所示:

int (*M)[cols] = malloc(rows * sizeof *M);

这将M声明为指向长度为intcols数组的指针,并请求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的声明允许您像使用它一样使用它。