C语言 DAY10 内存分配

1.引入

int nums[10] = {0}; //对
int len = 10;
int nums[len] = {0}; //错
是因为系统的内存分配原则导致的

2.概述

在系统运行时,系统为了更好的管理进程中的内存,所以将内存进行了分配,其分配的机制就称为内存分配

1.静态分配原则

1.特点

1、在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式。
2、必须事先知道所需空间的大小。
3、分配在栈区或全局变量区,一般以数组的形式。
4、按计划分配

2.动态分配原则

1.特点
1、在程序运行过程中,根据需要大小自由分配所需空间。
2、按需分配。
3、分配在堆区,一般使用特定的函数进行分配。
案例
班级有15个学员,定义数组记录学员成绩
double score[15] = {0};
记录学员成绩
1,输入学员数量
2,在堆区申请
3,扩展
4,释放
注意
在 c 语言中提供了一系列动态分配内存的函数
这些函数大部分都在 stdlib.h 头文件中声明
free 释放
malloc 申请空间 , 默认值随机
calloc 申请空间 , 默认值为 0
realloc 扩展空间
string.h 中提供的函数
memset 将 malloc 中的随机数设为 0

3.动态内存分配

memset函数

作用:重置

语法:

#include <string.h>

void *memset = (void *s,int c,size_t n);

s:原指针

c:重置后的数据

n:重置的数量

从s开始,将n个字节的数据,设置为c

示例:
#include<stdio.h>
#include<string.h>
int main(int argc, char const *argv[])
{
char strs[10] = {0};
memset(strs,'a',10*1);
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,10};
memset(nums,0,10 * 4);
for (int i = 0; i < 10; i++)
{
printf("%d ",nums[i]);
}
printf("\n");
return 0;
}

free函数

作用:释放空间

语法:

#include<stdlib.h>

void free(指针变量名);

malloc函数

作用:在堆中开辟一段内存空间

语法:

#include<stdlib.h>

void *malloc (size_t size);
参数:
size:开辟空间大小,单位字节,size_t可以理解为无符号int
返回值:
开辟的空间的地址
开辟失败返回NULL
注意:
1,在使用malloc需要判断是否开辟成功
2,如果多次 malloc 申请的内存,第 1 次和第 2 次申请的内存不一定是连续的
3,malloc的返回值在使用中记得强制类型转换
4,malloc从堆区申请空间后 空间的内容中的值是随机的(与局部变量一样大概率为0),可以使用
memset函数对空间中的数据进行置
示例:
#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));
//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;
}

calloc函数

作用:在堆中开辟一段内存空间

语法:

#include <stdlib.h>

void *calloc(size_t nmemb, size_t size);
参数:
nmemb:申请的块数
size:每块的大小
返回值:
开辟的空间的地址
开辟失败返回NULL
int *p = malloc(10 * sizeof(int));
int *p = calloc(10,sizeof(int));

示例:
#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
注意 :
新地址不一定等于原地址, 但是大概率相同
示例:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
int *p = (int *)calloc(3,sizeof(int));
int *p2 = (int *)calloc(3,sizeof(int));
//...
p = realloc(p,20);
for(int i = 0; i < 5; i++)
{
scanf("%d",&p[i]);
}
for(int i = 0; i < 5; i++)
{
printf("%d,",p[i]);
}
printf("\n");
free(p);
return 0;
}

4.内存泄露

概念:
申请的内存,首地址丢了,找不了,再也没法使用了,也没法释放了,这块内存就被泄
露了。
情况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;
}

相关推荐
吴声子夜歌几秒前
Java——显示锁
java·开发语言
思麟呀4 分钟前
在C++基础上理解Csharp-2
开发语言·jvm·c++·c#
桀人6 分钟前
类和对象——上篇
开发语言·c++
zzzsde10 分钟前
【Linux】线程概念与控制(3):线程ID&&C++封装线程
linux·运维·服务器·开发语言·算法
老花眼猫15 分钟前
C语言矩形旋转算法介绍
c语言·经验分享·青少年编程·课程设计
消失的旧时光-194316 分钟前
C 语言如何实现“面向对象”?—— 从 struct + 函数指针,到 Linux 内核设计思想
linux·c语言·开发语言
handler0118 分钟前
滑动窗口(同向双指针)算法:模板与例题解析
c语言·c++·笔记·算法·蓝桥杯·双指针·滑动窗口
小短腿的代码世界33 分钟前
Qt时间日期处理与QTimer高级应用:从毫秒级精度到跨平台定时器的完整架构解析
开发语言·qt·架构
TAN-90°-38 分钟前
Java 6——成员变量初始值 object equals和== toString instanceof 参数传递问题
java·开发语言
故事和你911 小时前
洛谷-【图论2-1】树6
开发语言·数据结构·c++·算法·深度优先·动态规划·图论