只有一样东西令梦想无法成真,那就是担心失败。
引入
示例
int num[10] = {0}; //√
int len = 10;
int num[len] = {0}; //×
因为系统的内存分配原则导致的
概述
在程序运行时,系统为了更好的管理进程中的内存,所以有了将内存进行了分配,其分配机制就称之为内存分配
分配原则
静态分配原则
特点:
1.在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式
2.必须实现知道所需空间的大小
3.分配在栈区或全局变量区,一般以数组的形式
4.按计划分配
动态分配原则
特点:
1.在程序运行中,根据需要大小自由分配所需要空间
2.按需分配
3.分配在堆区,一般使用特定的函数进行分配
如:
班级有20个学生,定义数组记录学员的成绩
double score[20] = {0};
记录学员成绩
1.输入学员数量
2.在堆区申请
3.扩展
4.释放
注意
在C语言中提供了一系列动态分配内存的函数,这些函数大部分都在stdlib.h头文件中声明
free 释放
malloc 申请空间,默认值随机
calloc 申请空间,默认值为0
realloc 扩展空间
string.h中提供的函数
memset 将malloc中的随机数设为0
所以导致申请空间时用那个都一样
动态分配函数
memset函数
作用:重置
语法
#include <string.h>
void *memset(void *s, int c ,size_t n);
参数
s:开始的位置
c:重置后的数据
n:重置的数量
示例
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char strs[10] = {0};
memset(strs,'a',1*10);
for (int i = 0; i < 10; i++)
{
printf("%c ",strs[i]);
}
printf("\n");
int nums[10] = {1,2,3,4,5,6,7,8,9,0};
memset(nums,0,4*10);
for (int i = 0; i < 10; i++)
{
printf("%d ",nums[i]);
}
printf("\n");
return 0;
}
free函数
作用:释放空间
语法
#include <stdlib.h>
void free(void *ptr);
参数:
ptr:指针
malloc函数
作用:在堆内存中开辟空间
语法
void *malloc(size_t size)
参数:
size:开辟空间大小,单位为字节,size_t可以理解为无符号int
返回值:
开辟空间的地址
开辟失败返回NULL
注意:
1.在使用malloc需要判断是否开辟成功
2.如果多次使用malloc申请内存,在第一次和第二次申请的内存不一定是连续的
3.malloc的返回值在使用时需要进行强制类型转换
4.malloc从堆区申请空间后,空间内容中的值是随机的(与局部变量相同,大概率值为0),可以使用memset函数对空间中的值进行重置
示例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
//1.申请内存空间
//申请一个可以存储10个int数据空间
int *p = (int *)malloc(sizeof(int) * 10);
//2.判断是否开辟失败
if (p == NULL)
{
printf("开辟失败\n");
return 0;
}
//重置为0
memset(p,0,4* 10);
//3.使用空间
for (int i = 0; i < 10; i++)
{
printf("%d ",p[i]);
}
printf("\n");
//4.释放空间
free(p);
return 0;
}
calloc函数
作用:在堆内存在开辟空间
语法
void *calloc(size_t nmemb, size_t size) ;
参数:
nmemb:申请的块数
size:每块的大小
返回值:
开辟空间的地址
开辟失败时返回NULL
int *p = malloc(sizeof(int) * 10);
int *p = calloc(sizeof(int) * 10);
示例
include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
//1,申请空间
//申请一个可以存储10个int数据的空间
// int *p = (int *)malloc(10 * sizeof(int));
int *p = (int *) calloc(10,sizeof(int));
//2,判断是否开辟失败
if (p == NULL)
{
printf("开辟失败\n");
return 0;
}
//置0
//memset(p,0,10 *sizeof(int));
//3,使用空间
for (int i = 0; i < 10; i++)
{
scanf("%d",&p[i]);
}
for (int i = 0; i < 10; i++)
{
printf("%d ",p[i]);
}
printf("\n");
//4,释放空间
free(p);
return 0;
}
realloc函数
作用:扩展空间
语法
void *realloc(void * ptr,size_t size);
参数:
ptr:原指针
size:从新开辟大小的大小,原大小 + 新开辟的大小
返回值:
开辟成功返回新地址
开辟失败返回NULL
注意:
新地址不一定等于原地址,但是大概率相同
内存泄漏
概念
类似于申请的内存首地址丢了,找不到了,没法使用了,没法释放了,这些情况称之为内存泄漏
情况1:记录申请内存的指针变量指向了别的地方
int *p = (int *) malloc(40);
int nums[10] = {};
p = nums;
情况2:在函数中申请空间,但使用完毕没有释放
void test()
{
int *p = (int *)malloc(40);
}
test();
防止多次释放
示例
int *p = (int *)malloc(40);
free(p);
free(p);
//多次释放时会报错
要点:释放前判断,释放后置NULL
int *p = (int *)malloc(40);
if (p != NULL)
{
free(p);
p = NULL;
}
if (p != NULL)
{
free(p);
p = NULL;
}