C语言 通过 calloc 分配的多维数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16715633/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multidimensional arrays allocated through calloc
提问by Kitchi
I have a question about how memory is allocated when I calloc. I had a look at thisquestion, but it doesn't address how memory is allocated in the case of a dynamically allocated two dimensional array.
我有一个关于如何分配内存的问题calloc。我看过这个问题,但它没有解决在动态分配的二维数组的情况下如何分配内存。
I was wondering if there was a difference in the memory representation between the following three ways of dynamically allocating a 2D array.
我想知道以下三种动态分配二维数组的方法之间的内存表示是否存在差异。
Type 1:
类型 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]
Type 2:
类型 2:
double **array1;
int ii;
array1 = calloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
Type 3:
类型 3:
double **array1;
int ii;
array1 = malloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
From what I understand of callocand malloc, the difference between the last two is that callocwill zero all the elements of the array, whereas mallocwill not. But are the first two ways of defining the array equivalent in memory?
根据我对callocand 的理解,malloc最后两个之间的区别在于calloc将数组的所有元素归零,而malloc不会。但是在内存中定义数组的前两种方法是否等效?
采纳答案by Ziezi
Are the first two ways of defining the array equivalent in memory?
定义数组的前两种方法在内存中是否等效?
Not quite. In the second type they are almost certainly contiguous, while in the first type this is not sure.
不完全的。在第二种类型中,它们几乎可以肯定是连续的,而在第一种类型中,这是不确定的。
Type 1:in-memory representation will look like this:
类型 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| | |
+---+
Type 2:in-memory representation will look like this:
类型 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| | |
+---+
回答by Monis Majeed
Simple Example
简单示例
#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;
}
回答by Marrow Gnawer
In the first way, you allocate 10 pointers to double, and 100 double. In the second way you allocate 100 pointers to double.The other difference is that in the second way, you allocate one big block of memory, so that all the elements of your array are in the same block. In the first way, each "row" of your array is in a different block than the others. Though, in the second way, your array should be a double* instead of a double**, because in this way of allocating, your array only contains pointers to double, not double.
在第一种方式中,您分配了 10 个指针给 double 和 100 个 double。在第二种方式中,您将 100 个指针分配给 double。另一个不同之处在于,在第二种方式中,您分配了一大块内存,以便数组的所有元素都在同一块中。在第一种方式中,数组的每一“行”与其他“行”位于不同的块中。但是,在第二种方式中,您的数组应该是 double* 而不是 double**,因为在这种分配方式中,您的数组只包含指向 double 的指针,而不是 double。
回答by susundberg
On the case 1, you make:
在案例 1 中,您使:
array1[0] -> [memory area of 10]
array1[1] -> [memory area of 10] ...
array1[N] -> [memory area of 10] ...
Note: You cannot assume that the memory area is continuous, there might be gaps.
注意:不能假设内存区域是连续的,可能会有间隙。
On the case 2 you make:
在案例 2 中,您:
array1 -> [memory area of 100]
The case 3 is same as the case 2, but its not initializing the memory. Difference between case 1 and 2 & 3 is that on the first case you really have 2D memory structure. For example if you want to swap rows 1 and 2, you could just swap the pointers:
情况 3 与情况 2 相同,但不初始化内存。情况 1 和 2 & 3 之间的区别在于,在第一种情况下,您确实拥有 2D 内存结构。例如,如果要交换第 1 行和第 2 行,则只需交换指针:
help = array1[1]
array1[1] = array1[2]
array1[2] = help
But if you want to do the same in the 2&3 case you need to do real memcpy. What to use? Depends what you are doing.
但是如果你想在 2&3 的情况下做同样的事情,你需要做真正的 memcpy。用什么?取决于你在做什么。
The first way uses bit more memory: if you would have array of 1000x10 then the first version will use 1000*8 + 1000*10*8 (on 64bit system), while the 2&3 will only use 1000*10*8.
第一种方法使用更多的内存:如果你有 1000x10 的数组,那么第一个版本将使用 1000*8 + 1000*10*8(在 64 位系统上),而 2&3 将只使用 1000*10*8。

