12

我有一个关于在calloc. 我看了一下这个问题,但它没有解决在动态分配的二维数组的情况下如何分配内存。

我想知道以下三种动态分配二维数组的方式之间的内存表示是否存在差异。

类型 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]

根据我对callocand的理解malloc,最后两者之间的区别在于calloc它将数组的所有元素归零,而malloc不会。但是在内存中定义数组的前两种方法是等效的吗?

4

4 回答 4

9

在内存中定义数组的前两种方法是否等效?

不完全的。在第二种类型中,它们几乎可以肯定是连续的,而在第一种类型中则不确定。

类型 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| | |
          +---+
于 2015-10-15T19:01:45.267 回答
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;
}
于 2014-02-21T08:57:29.773 回答
0

在第一种方式中,分配 10 个指针给 double 和 100 个 double。在第二种方式中,您分配了 100 个指向 double 的指针。另一个区别是,在第二种方式中,您分配了一大块内存,因此数组的所有元素都在同一个块中。在第一种方式中,数组的每个“行”都与其他“行”位于不同的块中。但是,在第二种方式中,您的数组应该是 double* 而不是 double**,因为在这种分配方式中,您的数组只包含指向 double 的指针,而不是 double 的指针。

于 2013-05-23T13:53:33.487 回答
0

在案例 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&3 的情况下做同样的事情,你需要做真正的 memcpy。用什么?取决于你在做什么。

第一种方法使用更多内存:如果您有 1000x10 的数组,那么第一个版本将使用 1000*8 + 1000*10*8(在 64 位系统上),而 2&3 将仅使用 1000*10*8。

于 2013-05-23T14:23:05.107 回答