我有一个关于在calloc
时如何分配内存的问题。我查看了this问题,但它没有说明在动态分配的二维数组的情况下如何分配内存。
我想知道以下三种动态分配2D数组的方式之间的内存表示是否存在差异。
类型1:
double **array1;
int ii;
array1 = calloc(10, sizeof(double *));
for(ii = 0; ii < 10; ii++) {
array1[ii] = calloc(10, sizeof(double));
}
// Then access array elements like array1[ii][jj]
类型2:
double **array1;
int ii;
array1 = calloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
类型3:
double **array1;
int ii;
array1 = malloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
根据我对calloc
和malloc
的理解,后两者之间的区别在于calloc
会将数组的所有元素归零,而malloc
则不会。但是前两种在内存中定义数组的方法是什么?
答案 0 :(得分:7)
前两种在内存中定义数组的方法是什么?
不完全。在第二种类型中,它们几乎肯定是连续的,而在第一种类型中,这是不确定的。
类型1:内存中表示将如下所示:
+---+---+---+---+---+---+---+---+---+---+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+---+---+
^
|------------------------------------
. . . . . . . . | // ten rows of doubles
-
+---+---+---+---+---+---+---+---+---+--|+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0||
+---+---+---+---+---+---+---+---+---+--|+
^ . . . -
| ^ ^ ^ . . . . . |
| | | | ^ ^ ^ ^ ^ |
+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // each cell points to ten doubles
+---+---+---+---+---+---+---+---+---+---+
^
|
|
+-|-+
array1| | |
+---+
类型2:内存中表示将如下所示:
+---+---+---+---+---+---+---+---+---+---+ +---+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 |
+---+---+---+---+---+---+---+---+---+---+ +---+
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | | | |
| | | | | | | | | | |
+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+ +-|-+
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |99 | // each cell points to one double
+---+---+---+---+---+---+---+---+---+---+ +---+
^
|
|
+-|-+
array1| | |
+---+
答案 1 :(得分:1)
简单示例
#include<stdio.h>
#include<stdlib.h>
int **d ;
int sum();
//----------------------------------------------
int main(){
d = (int **)calloc(3,sizeof(int*));
printf("\n%d",sum());
}
//-----------------------------------------------
int sum(){
int s = 0;
for(int i = 0; i < 3; i++)
d[i] = (int *) calloc (3,sizeof(int));
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
d[i][j] = i+j;
s += d[i][j];
printf("\n array[%d][%d]-> %d",i,j,d[i][j]);
}
}
return s;
}
答案 2 :(得分:-1)
在第一种方式中,您将10个指针分配给double,并指定100个double。在第二种方式中,您将100个指针分配给double。另一个区别是,在第二种方式中,您分配一个大的内存块,以便您的数组的所有元素都在同一个块中。在第一种方式中,阵列的每个“行”与其他块不同。 虽然,在第二种方式中,你的数组应该是double *而不是double **,因为在这种分配方式中,你的数组只包含指向double的指针,而不是double。
答案 3 :(得分:-1)
在案例1上,你做了:
array1[0] -> [memory area of 10]
array1[1] -> [memory area of 10] ...
array1[N] -> [memory area of 10] ...
注意:您不能假设内存区域是连续的,可能存在间隙。
在案例2中你做了:
array1 -> [memory area of 100]
情况3与情况2相同,但它没有初始化存储器。案例1和案例2之间的区别3是在第一种情况下你真的有2D内存结构。例如,如果要交换行1和2,则只需交换指针:
help = array1[1]
array1[1] = array1[2]
array1[2] = help
但是如果你想在2&amp; 3的情况下做同样的事情,你需要做真实的memcpy。用什么?取决于你在做什么。
第一种方式使用更多的内存:如果你有1000x10的数组,那么第一个版本将使用1000 * 8 + 1000 * 10 * 8(在64位系统上),而2&amp; 3将只使用1000 * 10 * 8。