二维数组的动态内存分配

时间:2020-03-30 17:04:38

标签: c arrays pointers memory dynamic-memory-allocation

在此代码中,虽然我们为2D数组动态分配内存,但是在4位地址之后为什么占用16个字节的间隙,但是当我们静态分配2D数组时,它没有这种间隙..这是什么原因??

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    int r = 3, c = 4, i, j, count; 

    int stat[r][c];

    int *arr[r]; 
    for (i=0; i<r; i++) 
         arr[i] = (int *)malloc(c * sizeof(int)); 

    // Note that arr[i][j] is same as *(*(arr+i)+j) 
    count = 0; 
    for (i = 0; i <  r; i++) 
      for (j = 0; j < c; j++) 
         arr[i][j] = ++count; // Or *(*(arr+i)+j) = ++count 

    for (i = 0; i <  r; i++) 
      for (j = 0; j < c; j++) 
         printf("%d\n", *(arr+i)+j); 

    printf("\n\n");  
    for (i = 0; i <  r; i++) 
      for (j = 0; j < c; j++) 
         printf("%d\n", *(stat+i)+j); 

    /* Code for further processing and free the  
      dynamically allocated memory */

   return 0; 
} 

2 个答案:

答案 0 :(得分:2)

因为您没有分配2D数组。您正在分配一组一维数组,并且这些分配不必是连续的(大多数malloc实现保留一些字节来存储分配的块的大小)。

要动态分配“真正的”二维数组,直到运行时才知道行数和列数,您可以执行以下操作:

stat (*arr)[c] = malloc( sizeof *arr * r );

与任何“常规”二维数组一样,都是连续的。

但是...

严格来说,此行为是不确定的-由于arr指向VLA,因此sizeof *arr表达式必须在运行时而不是在编译时以及{{ 1}}当时不是有效的指针值。我从未在使用过的任何实现上看到此失败,但这并不意味着它不会在某处失败。如果arr是常量,例如

c

那么就不会有问题,这将是动态分配Nx3数组的首选方法。

如果您需要所有数组元素都是连续的(这样就可以使用指针或类似的东西遍历整个数组),那么最安全的选择是将内存分配为一维数组:

stat (*arr)[3] = malloc( sizeof *arr * r );

并手动计算偏移量:

stat *arr = malloc( sizeof *arr * r * c );

如果想要方便的2D表示法,可以尝试创建一个指针并设置为指向数组的开头,例如

x = arr[ i * r + j ];

,但是如果指针类型不兼容,则这种指针别名也没有定义,我们没有理由期望指向stat (*ptr)[c] = (stat (*)[c]) arr; 的指针与指向{{1}的数组的指针兼容}。

答案 1 :(得分:1)

关于您问题的评论提供了最基本的建议-不必担心malloc将您的内存放在何处。无法保证会以任何顺序进行。它可能会为了进行各种优化或推测而定位分配,并且每次执行可能会有所不同。如果没有其他问题,则在您对malloc的调用之间进行其他内存分配,对空闲的垃圾回收的调用(即使用GC的语言)将影响下一个分配的位置。

这也可能因编译器,编译器选项,操作系统等而异。

由于特定原因,您的分配有16个字节的间隔,如果没有更多而且可能非常深入的了解您的方案,这是不可能说的。顺便说一句,您没有在问题中包含printf的输出。

但是,如果我不得不猜测,我会说内存管理器正在根据内存边界对齐分配…也许是32字节或64字节边界。

您正在分配4 * sizeof(int)。如果系统上的int为4字节,则为16字节。如果您的malloc喜欢将行最多排成32个字节,则可能解释了您看到的16个字节的间隙。

但是,再次……这只是一个猜测。简单的答案是...您不在乎。

但是如果您出于某些原因 DO 关心您,则可能需要自己进行分配。 malloc占用更大的内存,然后在内部管理自己的指针和分配。

相关问题