通过calloc分配的多维数组

时间:2013-05-23 13:46:14

标签: c malloc calloc

我有一个关于在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]

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

4 个答案:

答案 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。

相关问题