1.动态内存分配是什么
C语言中的动态内存分配是指在程序运行时根据需要动态地分配和释放内存空间。这与静态内存分配相对,静态内存分配是在编译时确定内存分配的大小。
2.为什么要进行动态内存分配
我们已经掌握的内存开辟⽅式有:
int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
3.C语言中动态内存分配函数
下面的四个动态内存函数都需要引入头文件<stdlib.h>
malloc
malloc 是我们见得最多的动态内存函数。
int *ptr1 = (int *)malloc(10 * sizeof(int));
-
int *ptr1
: 这声明了一个指针变量ptr1
,它指向整型数据。 -
malloc(10 * sizeof(int))
: 这部分调用了malloc()
函数来分配内存空间。malloc()
函数接受一个参数,即要分配的字节数。在这里,我们请求分配的内存空间大小是 10 个整型数据的大小。sizeof(int)
表示一个整型数据的字节数。因此,10 * sizeof(int)
表示了我们要分配的内存空间的总字节数。 -
(int *)
: 这部分是对malloc()
返回的指针进行类型转换。malloc()
返回的是void *
类型的指针,我们将其转换为int *
类型,以便与ptr1
的类型匹配。
总结起来,这句代码的作用是:分配了能够存储 10 个整型数据的内存空间,并将该内存空间的首地址存储在 ptr1
指针变量中。
这个函数向内存申请⼀块连续可⽤的空间,并返回指向这块空间的指针。
free
#include <stdio.h>
#include <stdlib.h>
int main() {
// 使用malloc动态分配10个整数的内存空间
int *ptr = (int *)malloc(10 * sizeof(int));
if (ptr == NULL) {
printf("内存分配失败!\n");
return 1;
}
// 使用动态分配的内存空间进行一些操作
for (int i = 0; i < 10; ++i) {
ptr[i] = i * 10;
}
// 打印动态分配的内存空间中的值
printf("动态分配的内存空间中的值:\n");
for (int i = 0; i < 10; ++i) {
printf("%d ", ptr[i]);
}
printf("\n");
// 使用完动态分配的内存空间后,释放内存
free(ptr);
ptr = NULL;
return 0;
}
在这个示例中,首先使用 malloc()
分配了一个包含 10 个整数的内存空间,然后通过循环对这些动态分配的内存进行了一些操作。最后,通过调用 free()
函数释放了动态分配的内存空间。
使用 free()
函数时,只需将要释放的内存块的指针作为参数传递给该函数即可。注意,使用 free()
释放的内存块应该是通过 malloc()
、calloc()
或 realloc()
分配的内存空间,否则行为是未定义的。
在释放完内存后,将指针变量 ptr
置为空指针是一个良好的编程习惯,这有助于避免悬空指针的问题。悬空指针是指在释放内存后,未将指针置为空,导致该指针仍然指向之前分配的内存地址,但该内存空间已经被释放,因此访问该指针可能会导致未定义的行为。
因此,通常建议在释放内存后,将指针置为空指针,即 ptr = NULL;
。这样,即使后续代码中存在误用已释放的指针,由于指针已经被置为空,程序在尝试使用该指针时会触发空指针异常,从而更容易发现和调试问题。
calloc
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)calloc(10, sizeof(int));
if (NULL != p)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
}
free(p);
p = NULL;
return 0;
}
realloc
int *ptr3 = (int *)realloc(ptr1, 20 * sizeof(int));
-
int *ptr3
: 这是一个指针变量ptr3
,它被声明为指向整数的指针。 -
(int *)
: 这是一个类型转换操作符,它将realloc()
函数返回的指针从void *
类型转换为int *
类型,以便与ptr3
的类型匹配。 -
realloc(ptr1, 20 * sizeof(int))
: 这是调用realloc()
函数来重新调整之前分配的内存块的大小。realloc()
函数接受两个参数:第一个参数是之前分配的内存块的指针,第二个参数是重新调整后的大小(以字节为单位)。在这里,我们将之前分配的内存块ptr1
的大小调整为可以容纳 20 个整数的内存空间,每个整数的大小是sizeof(int)
字节。 -
整个表达式的结果就是一个指向重新分配的内存空间的指针,该内存空间可以容纳 20 个整数。
需要注意的是,realloc()
函数可能会将之前分配的内存块移动到新的位置,或者在原地扩展内存块的大小。因此,如果调用 realloc()
函数成功,应该将返回的指针赋值给原指针变量(ptr1
),以确保我们仍然可以访问到调整后的内存块。如果调用失败,返回值为 NULL
,原来的内存块保持不变。