【问题标题】:C - dynamic matrix allocation: something doesn't make sense to meC - 动态矩阵分配:有些东西对我来说没有意义
【发布时间】:2018-07-26 14:31:27
【问题描述】:

我想知道为什么会这样

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

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

【问题讨论】:

  • 你错了。 (好吧,如果你不是,你就不会问这个。)第二个是,不管它的尺寸如何,一个指向指针数组的指针。哪些尚未分配。
  • 另见this方法:矩阵作为抽象数据类型。

标签: c pointers matrix dynamic allocation


【解决方案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() 为每一行释放动态分配的内存,以避免内存泄漏

【讨论】:

  • 虽然M = malloc(row*sizeof(int*));Mint ** 时有效。当M 是任何指针类型时,M = malloc(row * sizeof *M); 有效。更容易编码、审查和维护。
  • 完美 @chux sizeof(*M) 对我来说更有意义,它适用于任何指针类型。感谢您指出这一点。
【解决方案2】:

int ** 应该指向一个int*。这里你已经分配了一些内存——准确地说是sizeof(int)*rows*cols字节,然后你使用M[i]等。这里M[i]基本上是*(M+i),我们将访问i*sizeof(int*)malloc返回的一个地址的偏移量,但是你分配给rows*cols int 不是int*-s - 所以你最终会访问你不应该访问的内存(通常在sizeof(int*) &gt; 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 数组的情况下访问内存的方式。所以在这里使用双指针是没有意义的。你的所作所为是合法的。

在这两种情况下,它们都应该是双指针

不,他们不应该。第一个与第二个不同。无论如何,它们并不表示同一件事。

【讨论】:

    【解决方案3】:

    其他答案(建议malloc 用于Mn mallocs 用于行)是正确的,但不是分配矩阵的最有效方法。但是,您可以只使用一个 malloc 调用来分配矩阵,同时仍然允许您使用 M[i][j] 按行和列对其进行索引,如下所示:

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

    这将 M 声明为 指向长度为 colsint 数组的指针 并请求 malloc 分配 rows 数量的此类数组,这意味着您得到一个块rows * colsints (sizeof *M == sizeof(int) * cols)。

    malloc 成功时,您可以使用M,就像它被声明为int M[rows][cols] 一样,您可以使用

    scanf("%d", &M[i][j]);
    

    它看起来更复杂,但将M 分配为一个连续的内存块,这允许处理器优化对它的访问。

    作为额外的奖励,您还可以一键释放它:

    free(M);
    

    这确实需要 C99 支持,或者至少支持可变长度数组,但矩阵本身并不是一个合适的可变长度数组。它仍然由malloc 分配,但M 的声明允许您像使用它一样使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      相关资源
      最近更新 更多