C语言——动态内存申请

引入

#include <stdio.h>
int main(int argc, char const *argv[])
{
int len = 0;
printf(" 请输入数组长度 \n");
scanf("%d",&len);
// 此时我们想将数组的长度动态设定 , 但是语法不支持
int nums[len] = {0};
return 0;
}

动态内存作用

在开发中根据实际需求开辟内存

内存申请分类

静态内存申请(静态分配)

1.在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式。
int [10]
2.必须事先知道所需空间的大小
3.分配在栈区或全局变量区,一般以数据的形式
4.按计划分配
特点:在程序运行中无法对其分配的内存进行修改

动态内存申请(动态内存)

1.在程序运行过程中,根据需要大小自由分配所需空间
2.按需分配
3.分配在堆区,一般使用函数对其内存进行动态分配

动态分配函数

注意
以下函数由系统提供,属于库函数
意味着无需自己定义该函数,直接调用即可
因为动态内存分配的内存在堆区,无法自动释放内存,需要手动释放内容

memset

作用

将指定开始位置到指定长度的内存中的内容设置为指定的值

语法

void *memset(void *s, int c, size_t n);
参数 :
void *s: 开始位置
int c: 指定的内容
n: 设定的长度
返回值 :
设置的内存的首地址

所属头文件

#include <string.h>

free

作用

释放动态分配申请的内存

语法

void free(void *ptr);
参数 :
void *ptr: 要释放的内存的首地址
返回值 :
void: 没有返回值

所属的头文件

#include <stdlib.h>

malloc

作用

动态申请内存

在堆区

语法

void *malloc(size_t size);
参数 :
size_t size: 申请的内存大小 , 单位字节
返回值 :
void *: 申请的内存的首地址 , 如果为 NULL 说明申请失败

所属头文件

#include<stdlib.h>

示例

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 根据用户输入数量 , 动态申请内存 , 存储 int 型数据
int len = 0;
printf(" 请输入存储的数的个数 \n");
scanf("%d",&len);
// 申请空间
void *nums = malloc(len * sizeof(int));
if (nums == NULL)
{
printf(" 申请失败 \n");
return 0;
}
int *p = (int *) nums;
for (int i = 0; i < len; i++)
{
printf("%d\n",p[i]);
}
// 释放空间
free(p);
return 0;
}

calloc

作用

动态申请内存

在堆区

语法

void *calloc(size_t nmemb, size_t size);
参数 :
nmemb: 申请的内存块数
size: 每块所占的字节数
返回值 :
void *: 申请的内存的首地址 , 如果为 NULL 说明申请失败

所属头文件

#include<stdlib.h>

示例

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 根据用户输入数量 , 动态申请内存 , 存储 int 型数据
int len = 0;
printf(" 请输入存储的数的个数 \n");
scanf("%d",&len);
// 申请空间
int *nums = (int *)(calloc(len,sizeof(int)));
if (nums == NULL)
{
printf(" 申请失败 \n");
return 0;
}
for (int i = 0; i < len; i++)
{
printf("%d\n",nums[i]);
}
// 释放空间
free(nums);
return 0;
}

注意

malloc 和 calloc 函数都是用来申请内存的。
区别:
1) 函数的名字不一样
2) 参数的个数不一样
3) malloc 申请的内存,内存中存放的内容是随机的,不确定的,而 calloc 函数申
请的内存中的内容为 0

realloc

作用

追加内存

语法

void *realloc(void *ptr, size_t size);
参数 :
void *ptr: 要追加的内存的首地址
size: 重新申请的大小 , 单位字节
返回值 :
void *: 追加的内存的首地址 , 如果为 NULL 说明追加失败

注意

该函数并不是在原基础上追加,而是重新开辟一片内存,将原内存中的值拷贝
到新内存的前面

内存泄漏

概念

申请的空间,没有被指向,系统无法回收该空间。这种情况,就叫内存泄漏

情况1:指向堆区的指针变量,指向了别的地方

int *nums = calloc(10,4);// 指向 calloc 函数在堆内存开辟的空间的首地址
int x = 10;
nums = &x;// x 的地址赋值给 nums 变量

情况2:指向堆区的指针变量 被意外释放

void method()
{
int *nums = calloc(10,4);
}
int main()
{
method();
return 0;
}

总结

使用完成记得释放所用的内存

注意

重复释放同一片内存也会导致程序出现错误

如何避免重复释放

示例:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
char *p = malloc(100);
if(p != NULL){
free(p);
p = NULL;
}
if(p != NULL)
{
free(p);
p = NULL;
}
return 0;
}
总结:
在使用申请的内存后要释放并将原指针指向NULL
每次释放前判断该指针是否为NULL,如果不为空在释放并制空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值