引入
#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,如果不为空在释放并制空