引入
示例
1 :
int nums[10] = {0}; //对
int len = 10;
int nums[len] = {0}; //错
是因为系统的内存分配原则导致的
概述
在程序运行时,
系统为了更好的管理进程中的内存
,
所以有了将内存进行了分配
,
其分配的机制
就称为内存分配
分配原则:
静态分配原则
特点
:
1、在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式。
2、必须事先知道所需空间的大小。
3、分配在栈区或全局变量区,一般以数组的形式。
4、按计划分配。
动态分配原则
特点
:
1、在程序运行过程中,根据需要大小自由分配所需空间。
2、按需分配。
3、分配在堆区,一般使用特定的函数进行分配。
注意:
在
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:重置的数量
从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(void *ptr);
参数
:
ptr:指针
malloc函数
作用
:
在堆内存中开辟空间
语法:
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函数
作用
:
在堆内存中开辟空间
语法:
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
注意
:
新地址不一定等于原地址,
但是大概率相同
内存泄漏
概念
申请的内存,首地址丢了,找不了,再也没法使用了,也没法释放了,这块内存就被泄 露了。
情况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;
}