1

我正在尝试使用以下代码在 C 中分配一个动态二维数组:

int **allocateMatrix(int rows, int columns) {

    int i = 0;
    int **p = NULL;

    p = (int**) calloc(rows, sizeof(int*));
    for(; i < rows; i++) {

        p[i] = (int*) calloc(columns, sizeof(int));
    }

    return p;
}

该代码有效,但实际上它分配的内存是它需要的两倍。

例如,如果我传递参数rows = 2columns = 3得到一个 2 行乘 8 列的数组。

难道我做错了什么?

谢谢你。

编辑

矩阵的内容(从文件中加载)是:

-1 5 0
4 0 2

这是分配和赋值后内存的样子:

记忆

4

4 回答 4

3

它分配了正确的内存量,但它分配的内存比简单的 2D 数组使用的更多,因为您创建的不是简单的 2D 数组。

假设一个 32 位系统(sosizeof(int) == sizeof(int *)sizeof(int) == 4),那么:

  • 一个简单的二维数组需要 2 x 3 个整数 = 6 x 4 = 24 个字节
  • 动态二维数组需要 2 个指针加上 2 x 3 个整数 = 8 x 4 = 32 个字节

那是在内存分配中的任何开销之前。所以不是两次,而是更多。

您正在做的事情的优点是您可以编写p[i][j]并获得正确的结果。如果您模拟了一个简单的二维数组,则必须自己进行下标计算:p[i*3+j]或使用(*p)[i][j],具体取决于您定义指针的方式p

于 2013-11-14T22:23:24.250 回答
1

AFAICT,您对具有 20 个元素的数组的屏幕截图是因为..您告诉 Netbeans(用那个@20)显示从内存位置(**(matrix))开始的 20 个元素。当您将其更改为“@3”时会发生什么?

但是,基于此评论:

其实不止双倍。我知道,因为当我尝试分配值时,它们在内存中并不连续,而是被转移(我可以从 netbeans 调试窗口中的手表中看到它)。

当您分配内存时,您正在调用一个库,该库计算如何从操作系统请求它可能使用的空间,然后操作系统为它提供了哪些空间尚未使用。

您正在对分配器的工作方式做出可能正确或不正确的假设。它有可能以您意想不到的方式有效地分配空间,尤其是由于虚拟分页机制。简而言之,对分配器的连续调用并不能保证分配连续的内存,而且很少会这样。

如果您想将指针数组用于双数组样式结构并且绝对必须以更“预期”的方式具有连续地址,您可以尝试以下操作:

int **allocateMatrix(int rows, int columns) {

    int i = 0;
    int **p = NULL;
    int *d = NULL;


    p = (int**) calloc(rows, sizeof(int*));
    d = (int*) calloc(rows * columns, sizeof(int));

    for(; i < rows; i++) {
        p[i] = d + i * columns;
    }

    return p;
}

(代码未测试)

于 2013-11-14T22:26:07.300 回答
0

这不是因为它有一个二维数组大小(rows*columns*sizeof(int*))来存储指针和一个二维数组空间来存储实际值(rows*columns*sizeof(int))?

于 2013-11-14T22:29:34.420 回答
0

您可以使用以下方法(存储数据不需要额外的内存,实际上是内存中的一维连续数组):

#include <stdlib.h>
#include <stdio.h>

int (*allocateMatrix(int rows, int columns))[]{
    int (*p)[columns] = calloc(rows, columns * sizeof(int)),
        i, j;
    for (i = 0; i < rows; i++) {
      for (j = 0; j < columns; j++) {
        p[i][j] = rows*i + j;
      }
    }
    return p;
}


int main(int argc, char *argv[]) {
  int rows = 4, cols = 5,
     (*array)[cols] = allocateMatrix(rows,cols);

  int i, j;
  for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++) {
      printf("array[%d][%d] = %2d\n", i, j, array[i][j]);
    }
  }
  free(array);
  return 0;
}

输出:

array[0][0] =  0
array[0][1] =  1
array[0][2] =  2
array[0][3] =  3
array[0][4] =  4
array[1][0] =  4
array[1][1] =  5
array[1][2] =  6
array[1][3] =  7
array[1][4] =  8
array[2][0] =  8
array[2][1] =  9
array[2][2] = 10
array[2][3] = 11
array[2][4] = 12
array[3][0] = 12
array[3][1] = 13
array[3][2] = 14
array[3][3] = 15
array[3][4] = 16
于 2013-11-14T22:52:13.213 回答