c语言:深入理解动态内存管理(了解malloc,calloc,realloc,free函数的用法)

前言:为什么要有动态内存管

普通开辟空间的方法:

int a=10;//在栈空间上开辟4个字节
char ch=[10];//在栈空间上开辟10个字节的连续空间
上述的开辟空间的方式有两个特点:
1.空间开辟的大小是固定的
2.数组在声明的时候,必循指定数组的长度,数组空间一旦确定了,大小就不能调整了。
 
为此,c语言引入了动态内存这一概念,让程序员自己可以申请和释放空间,就比较灵活了。

 

动态内存管理的定义 

动态内存管理是指在程序运行时动态地分配和释放内存的过程。在动态内存管理中,程序可以根据需要在运行时分配内存空间,而不需要在编译时就确定内存的大小或数量。这使得程序能够更加灵活地处理不确定数量或大小的数据。


malloc函数

malloc是C语言中用于动态分配内存的函数,该函数的作用是在程序运行时,向操作系统请求分配一块特定大小的内存空间,并返回指向该内存空间起始地址的指针。

头文件:

下面是malloc函数的声明:

void *malloc(size_t size);
  • size参数表示需要分配的内存空间的大小,以字节为单位。
  • malloc函数返回一个void*类型的指针,指向分配的内存空间的起始地址。如果分配失败,则返回NULL

示例:

#include 
#include 

int main() 
{
    int *ptr; // 声明一个指向整数的指针

    int n = 5; // 定义整数n,表示需要分配的内存空间大小

    // 使用malloc函数动态分配包含5个整数的内存空间
    ptr = (int*)malloc(n * sizeof(int));
    if (ptr == NULL) 
    { // 检查内存分配是否成功
        printf("内存分配失败\n");
        return 1;
    }

    // 使用动态分配的内存空间进行初始化
    for (int i = 0; i < n; i++) 
    {
        ptr[i] = i * 2;
    }

    // 输出动态分配的内存空间中的数据
    printf("动态分配的内存空间中的数据:\n");
    for (int i = 0; i < n; i++)  
    {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放动态分配的内存空间
    free(ptr);

    return 0;
}

注意:使用malloc函数分配的内存空间在使用完毕后应该及时释放(free),以避免内存泄漏问题。此外,动态分配的内存空间不会自动初始化为零,因此在使用前需要确保对其进行正确的初始化。


free函数

free函数是C语言中用于释放动态分配的内存空间的函数,free函数的作用是将之前通过malloccallocrealloc等函数动态分配的内存空间返回给系统,以便系统可以重新分配这部分内存给其他程序使用。

头文件:

下面是free函数的声明:

void free(void *ptr);

示例:

#include 
#include 

int main() 
{
    int *ptr;
    int n = 5;

    // 分配包含5个整数的内存空间
    ptr = (int*)malloc(n * sizeof(int));
    if (ptr == NULL) 
    {
        printf("内存分配失败\n");
        return 1;
    }

    // 使用动态分配的内存空间
    for (int i = 0; i < n; i++) 
    {
        ptr[i] = i * 2;
    }

    // 释放动态分配的内存
    free(ptr);  // 使用free函数释放动态分配的内存
    ptr=NULL;//将指针设置为NULL

    return 0;
}

注意:一旦调用了free函数释放了动态分配的内存空间,就不应再使用指向该内存空间的指针,否则会导致未定义的行为。因此,释放内存后应该将指针设置为NULL,以避免出现悬空指针问题。


calloc函数

calloc函数是C语言中用于动态分配内存空间并初始化为零的函数,calloc函数分配的内存空间会被初始化为零,这是与malloc函数的一个区别。calloc函数通常用于分配数组或结构体等需要初始化为零的大块内存空间。

头文件:

下面是calloc函数的声明:

void *calloc(size_t num, size_t size);
  • num参数表示需要分配的元素个数。
  • size参数表示每个元素的大小(以字节为单位)。

calloc函数返回一个指向分配内存空间起始位置的指针,如果内存分配失败,则返回NULL

示例:

#include 
#include 

// 定义一个简单的结构体
typedef struct 
{
    int id;
    char name[20];
} Employee;

int main() 
{
    int numEmployees = 3;
    Employee *employees;

    // 分配包含3个Employee结构体的内存空间并初始化为零
    employees = (Employee*)calloc(numEmployees, sizeof(Employee));
    if (employees == NULL) 
    {
        printf("内存分配失败\n");
        return 1;
    }

    // 输出动态分配的结构体数组中的值
    for (int i = 0; i < numEmployees; i++) 
    {
        printf("ID: %d, Name: %s\n", employees[i].id, employees[i].name);  // 应该输出3个0和空字符串
    }

    // 释放动态分配的内存
    free(employees);
    employees=NULL;

    return 0;
}

realloc函数

realloc函数是C语言中用于重新分配已分配内存空间的函数,realloc函数可以用于扩大或缩小先前由malloccallocrealloc分配的内存块的大小。

头文件:

声明:

void *realloc(void *ptr, size_t size);
  • ptr参数是指向先前分配的内存空间的指针。
  • size参数是新的内存空间的大小(以字节为单位)。

realloc函数返回一个指向重新分配内存空间的指针。如果无法满足内存需求,或者ptrNULL,则realloc函数返回NULL,并且原内存块保持不变。

示例:

#include 
#include 

int main() 
{
    int *ptr;

    // 分配包含5个整数的内存空间
    ptr = (int*)malloc(5 * sizeof(int));
    if (ptr == NULL) 
    {
        printf("内存分配失败\n");
        return 1;
    }

    // 重新分配内存空间,扩大为包含10个整数
    ptr = (int*)realloc(ptr, 10 * sizeof(int));
    if (ptr == NULL) 
    {
        printf("内存重新分配失败\n");
        return 1;
    }

    // 释放动态分配的内存
    free(ptr);

    return 0;
}

注意:需要注意的是,realloc函数可能会将先前分配的内存块移动到新的位置,因此在调用realloc后,原始指针可能会变为无效。因此,建议在调用realloc后将返回的指针赋给原始指针,以确保在重新分配内存失败时不会丢失对原始内存块的引用。

9c390aaba26d4f8bb4f15b0a48dc4430.png

 

你可能感兴趣的:(c语言,c语言,开发语言,缓存,数据结构)