在此代码中,虽然我们为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;
}
答案 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
占用更大的内存,然后在内部管理自己的指针和分配。