第11章 动态内存分配

11.1 程序内存分配

分区:

栈区(stack):存放非局部变量

堆区(heap):存放malloc()等函数动态分配的数据

全局静态区:存放静态局部变量、全局变量

代码区:存放程序代码

动态内存分配指根据需要向系统申请所需大小的空间,由于未在声明部分定义其为变量或者数组,不通过变量名或者数组名来引这些数据,只能通过指针来引用。

11.2 void 指针(无类型指针)

C99允许定义一个类型为void的指针变量,它可以指向任何类型的数据

1、作用

指针变量必须有类型,否则编译器无法知道如何解读内存块保存的二进制数据。但是,有时候向系统请求内存的时候,还不确定会有什么类型的数据写入内存,需要要先获得内存块,稍后再确定写入的数据类型。

这种情况下就可以使用 void 指针,它只有内存块的地址信息,没有类型信息,等到使用该块内存的时候,再向编译器补充说明,里面的数据类型是什么。

2、特点

①void指针与其他所有类型指针之间是互相转换关系,任一类型的指针都可以转为void指针,而void指针也可以转换为任一类型的指针。

②由于不知道 void 指针指向什么类型的值,所以不能用 * 运算符取出它指向的值(解引用)。

int num = 42;
double pi = 3.14159;
// int 指针转为 void 指针
void *viPtr = #  // 隐式类型转换
// double 指针转为 void 指针
void *vdPtr = π   // 隐式类型转换
// void 指针转换为 int 指针并解引用
// int *intPtr = viPtr;    // 隐式类型转换
int *intPtr = (int *)viPtr;    // 显示类型转换
printf("整数值:%d \n", *intPtr);
// void 指针转换为 double 指针并解引用
// double *doublePtr = vdPtr;  // 隐式类型转换
double *doublePtr = (double *)vdPtr; // 显式类型转换
printf("浮点数:%f \n", *doublePtr);
// void 指针不能解引用 会报错
// printf("%d", *viPtr);
// printf("%d", *vdPtr);

11.3 内存分配相关函数

1、malloc函数

malloc()函数用于分配一块连续的内存空间

函数原型void *malloc(size_t size);size是要分配的内存块大小,以字节为单位

返回值说明:如果内存分配成功,返回一个void指针,指向新分配的内存块的地址;如果内存分配失败,返回一个空指针(NULL)

int *p;
p = (int *)malloc(sizeof(int));
// 判断是否分配成功
if (p == NULL)
{
    printf("内存分配失败\n");
    return 1; // 退出程序
}
// 使用解引用赋值并输出
*p = 120;
printf("p指向的地址:%p \n", p);
printf("p指向的值:%d", *p);
// 释放分配的内存
free(p);
2、calloc函数

calloc()函数用于分配内存并将其初始化为零,它在分配内存块时会x自动将内存中的每一个字节都设置为零

函数原型:void *calloc(size_t numElement, size_t sizeOfElement);numElement是要分配的元素的数量,sizeOfElement是每一个元素的大小(以字节为单位)

返回值说明:如果内存分配成功,返回一个 void 指针,指向新分配内存块的地址;如果分配失败(例如内存不足),返回一个空指针(NULL)。

    int *p;    // 定义整型指针
    int n = 5; // 定义数组长度
    // 动态分配内存,将地址赋给指针p
    p = (int *)calloc(n, sizeof(int));
    // 判断是否分配成功
    if (p == NULL)
    {
        printf("内存分配失败\n");
        return 1; // 退出程序
    }
    // 输出数组的元素的值
    for (int i = 0; i < n; i++)
    {
        printf("p[%d]=%d \n", i, p[i]);
    }
    // 释放分配的内存
    free(p);
3、realloc函数

realloc()函数用于重新分配malloc函数或者calloc函数所获得的内存块的大小

函数原型:void *realloc(void *ptr,size_t size);ptr是要重新分配的内存块的指针,size是新的内存块的大小(以字节为单位)

    int *b;
    // 分配内存
    b = malloc(sizeof(int) * 100);
    printf("b=%p, size:%zu \n", b, _msize(b));
    // 调整内存大小
    b = realloc(b, sizeof(int) * 2000);
    printf("b=%p, size:%zu \n", b, _msize(b));
    // 再次调整内存大小
    b = realloc(b, sizeof(int) * 200);
    printf("b=%p, size:%zu \n", b, _msize(b));
    // 释放内存
    free(b);
4、free函数

free() 函数用于释放动态分配的内存,以便将内存返回给操作系统,防止内存泄漏。

函数原型:void free(void *ptr);ptr是指向要释放的内存块的指针,ptr必须是malloc函数或者calloc函数动态分配的内存块地址。

注意:①分配的内存块一旦释放,就不应该再次操作已经释放的地址,也不应该再次使用free释放第二次。②如果忘记调用free函数,会地址无法访问未回收的内存块,构成内存泄漏。

11.1 内存分配的基本原则

1、避免分配大量的小内存块。 分配堆上的内存有一些系统开销,所以分配许多小的内存块比分配几个大内存块的系统开销大。
2、仅在需要时分配内存。 只要使用完堆上的内存块,就需要及时释放它,否则可能出现内存泄漏。
3、总是确保释放已分配的内存。 在编写分配内存的代码时,就要确定好在代码的什么地方释放内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mephisto_123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值