我正在尝试使用以下代码在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 = 2
和columns = 3
,我会得到一个2行乘8列的数组。
我做错了吗?
谢谢。
修改:
矩阵的内容(从文件加载)是:
-1 5 0
4 0 2
这就是在分配和赋值之后内存的样子:
答案 0 :(得分:3)
它正在分配正确的内存量,但它分配的内存比简单的2D数组要多,因为您创建的内容不是简单的2D数组。
假设有32位系统(sizeof(int) == sizeof(int *)
和sizeof(int) == 4
),那么:
那是在内存分配开销的任何因素之前。所以不是两次,而是更多。
您正在做的事情的优点是您可以撰写p[i][j]
并获得正确的结果。如果您模拟了一个简单的2D数组,则必须自己进行下标计算:p[i*3+j]
或使用(*p)[i][j]
,具体取决于您如何定义指针p
。
答案 1 :(得分:1)
AFAICT,你有20个元素的数组截图是因为..你告诉Netbeans(用@20
)从内存位置(**(matrix)
)开始显示20个元素。当你把它改成'@ 3'时会发生什么?
但是,基于此评论:
实际上它不仅仅是双倍。我知道,因为当我尝试分配值时,它们在内存中不是连续的,但是它们被移位(我可以在netbeans的调试窗口中看到它)。
当您分配内存时,您正在调用一个库,该库可以确定如何从操作系统请求它可以使用的空间,然后是操作系统给出的尚未使用的空间。< / p>
您正在假设分配器的工作方式可能正确也可能不正确。它可以以您不期望的方式有效地分配空间,尤其是由于虚拟分页机制。简而言之,对分配器的连续调用并不保证分配连续的内存,而且很少会这样。
如果你想为一个双数组样式结构使用一个指针数组,并且绝对必须以更“预期”的方式拥有连续的地址,你可以试试这个:
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;
}
(代码未经测试)
答案 2 :(得分:0)
这不是因为它有一个二维数组大小(rows * columns * sizeof(int *))来存储指针和一个二维数组空间来存储实际值(rows * columns * sizeof(int))?
答案 3 :(得分:0)
您可以使用以下方法(不需要额外的内存来存储数据,实际上是内存中的1D连续数组):
#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