5

对于这两种情况,访问数组或内存分配会有什么影响:

1.

    int **arr;
    arr = malloc( sizeof(int) * row * column );

2.

    int **arr;
    arr = malloc( sizeof(*arr) * row);
    for(i=0; i<row; i++)
        arr[i] = malloc( sizeof( **arr) * column));
4

1 回答 1

6
  • 首先,“影响”是您的第一种方法被破坏了。它不能通过int **指针工作。

    为了像您尝试在第一种方法中那样一次性分配一个二维数组,您实际上必须分配一个足够大小的一维数组

    int *arr = malloc( row * column * sizeof *arr );
    // Note: `int *`, not `int **`
    

    并通过手动索引重新计算来执行访问,例如,arr[i][j]您不必做arr[i * column + j].

    尝试将分配的指针存储在其中int **arr,然后访问您的数组,因为arr[i][j]这只会导致崩溃。

  • 其次,你的第二种方法是可以的。只是在第二种方法中,您实际上并不需要通过多个独立malloc调用来分配二级内存。可以一次性分配整个二级内存

    int **arr = malloc( row  * sizeof *arr );
    int *arr_data = malloc( row * column * sizeof *arr_data );
    

    然后在行之间分配预先分配的二级内存

    for (i = 0; i < row; i++)
      arr[i] = arr_data + i * column;
    

    (当然,如果您愿意,您可以独立分配行。它也可以。我想一次性分配它们的原因是为了更好地说明第一种方法和第二种方法之间的相似性,如下所述。)

现在,通过查看这两种方法,您可以很容易地看到它们本质上都在做同样的事情。唯一的区别是,在第一种方法中,您通过arr + i * column每次计算来即时找到行的开头(注意这arr[i * column + j]相当于(arr + i * column)[j])。在第二种方法中,您使用相同的公式预先计算所有行的开头arr_data + i * column,并将它们存储在单独的“行索引”数组中以供进一步使用arr

因此,它基本上归结为内存使用(第一种方法需要更少的内存)和速度(第二种方法可能但不一定更快)之间的权衡。同时,第二种方法支持 2D 数组访问的“自然”语法 - arr[i][j],而在第一种方法中,您必须使用更复杂的 1D 访问语法和索引重新计算。

于 2013-07-04T19:48:32.193 回答