1、一维数组动态分配内存:int num[5]
源码:
int main(void)
{
// 使用动态内存分配一个数组为 int num[5]
int *num = NULL;
int len = 5;
num = (int *)malloc(len * sizeof(int));
for (int i = 0; i < len; i++)
{
num[i] = i;
}
for (int i = 0; i < len; i++)
{
printf("num[%d] = %d, &num[%d] = %p\n", i, num[i], i, &num[i]);
}
if (num != NULL)
{
free(num);
num = NULL;
}
return 0;
}
① num = (int *)malloc(len * sizeof(int));
在堆区分配了5个int型的内存空间,并将该内存空间的首元素地址返回给指针num,创建了一个数组为int num[5],如下图所示:
② 分配在堆区的内存空间地址是连续的,打印的结果如下:
num[0] = 0, &num[0] = 01145B50
num[1] = 1, &num[1] = 01145B54
num[2] = 2, &num[2] = 01145B58
num[3] = 3, &num[3] = 01145B5C
num[4] = 4, &num[4] = 01145B60
地址是4个字节递增的,因为这里int型是4字节的,它跟在栈区定义数组 int num[5] 是一致的。
③ 在堆区动态分配的内存需要进行手动释放,不然会造成内存泄漏,使用free(num)。
2、二维数组动态分配内存:char ptr[5][30]
源码:
int main(void)
{
int n = 5;
// char *ptr[5];
char **ptr = (char **)malloc(n * sizeof(char *));
if (ptr == NULL)
{
printf("malloc failed!\n");
return -1;
}
char buf[30];
for (int i = 0; i < n; i++)
{
// char ptr[5][30]
ptr[i] = (char *)malloc(30 * sizeof(char));
sprintf(buf, "Test%d:%d\n", i, i);
strcpy(ptr[i], buf);
}
for (int i = 0; i < n; i++)
{
printf("%s", ptr[i]);
}
for (int i = 0; i < n; i++)
{
if (ptr[i] != NULL)
{
free(ptr[i]);
ptr[i] = NULL;
}
}
if (ptr != NULL)
{
free(ptr);
ptr = NULL;
}
system("pause");
return 0;
}
① char **ptr = (char **)malloc(n * sizeof(char *));
在堆区分配了5个char *指针类型的内存空间,并将该内存空间的首元素地址返回给二级指针ptr,相当于char *ptr[5]。
注意:这里返回给二级指针是因为malloc分配完成后会将分配的内存空间首元素地址进行返回,而内存空间是5个char *的指针类型,即首元素是指针,返回的是指针的地址,所以需要使用二级指针取保存一级指针的地址。
② ptr[i] = (char *)malloc(30 * sizeof(char));
在上面因为只分配了一个在堆区的内存空间存放5个char *类型,但是每个指针需要的内存空间是还没有分配的,所以需要对这5个指针在堆区内再次进行分配内存空间为30个char类型,相当于分配了二维数组ptr[5][30],如下图:
③ 最后要释放在堆区分配的内存空间,不然会造成内存泄漏,释放顺序是先将ptr[0]-ptr[4]这5个分配的30个char类型字节的内存空间释放掉,接着再将二级指针ptr所指向在堆区分配的5个char *类型的内存空间给释放掉。