动态内存总结

目录:

一、如何开辟动态内存

二、对内存进行初始化

1.引用库函数进行初始化

2.使用calloc函数进行初始化

三、对内存进行扩容

1.内存不足,扩容失败,realloc函数返回空
2.堆内存足够:有两种情况

四、例题的总结

 一、如何开辟动态内存

我们用一张图进行说明:这里主要用到了malloc函数

在这里我们要注意的是:动态内存在堆中开辟,而我们的main程序是在栈中开辟。 

 二、对内存进行初始化

1.引用库函数进行初始化:

引用头文件:#include<string.h>
memset(p,0,sizeof(int)*10)     //初始化内存空间
括号里值的含义:

memset(初始化的内存地址(void*),初始化的值,初始化字节大小(size_t size));)

代码如下:

#include<string.h>
#include<stdio.h>
int main(){
	int* p = (int*)malloc(sizeof(int) * 10);
	assert(p != NULL);
	memset(p, 0, sizeof(int) * 10);
	for (int i = 0; i < 10; i++) {
		printf("%5d", p[i]);
	}
	free(p);
	p = NULL;
}
    0    0    0    0    0    0    0    0    0    0
D:\c程序\p1-8\Debug\p1-8.exe (进程 2692)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

但是我们要注意的是:申请的内存空间按照字节为单位,比如,我们将初始化的值改为1,

memset(p,1,sizeof(int)*10);我们发现程序并不是十进制的数字1

16843009
16843009
16843009
16843009
16843009
16843009
16843009
16843009
16843009
16843009

D:\c程序\p1-8\Debug\p1-8.exe (进程 20828)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

接下来我们将16843009用计算机转化为16进制,看一下结果

 我们发现,memset函数中初始化的值是将每个字节初始化1,而int刚好是4字节。

2.使用calloc进行初始化:

int *p=(int *)calloc (10,sizeof(int)); 

这句代码的意思是:相当于将字节大小为int的10 个整型初始化为0,我们这里calloc函数系统默认初始化的值为0。我们用代码运行一下:

三、对内存进行扩容

realloc:扩容操作或者缩容操作,扩容堆内存
int *q=(int*)realloc(p,15*sizeof(int));
realloc  扩容有三种情况   ,在已有的堆内存基础上进行扩容
1.内存不足,扩容失败,realloc函数返回空
2.堆内存足够:有两种情况

1)第一种情况:后续未分配的空间足够大,可以分配空间:
例如:int *p=malloc(10*sizeof(int));
          int *q=realloc(p,15*sizeof(int));
相当于原来有10个格子的空间,又续上了5个格子的空间,总共15个格子的空间
此时p==q(p和q的起始地址是一样的)

通过画图我们来解释一下:


2)第二种情况:后续未分配内存空间不足够大,不能分配空间:
例如: int *p=malloc(10*sizeof(int));
           int *q=realloc(p,15*sizeof(int));
相当于原来后续的格子不能放下扩容的5个格子,于是在一个新的堆空间重新开辟15个格子
并将前面p所指向的10个格子复制到后面新开辟的15个格子中。
此时p!=q(p和q的起始地址不一样)

通过画图我们来解释一下:

四、例题总结 

void GetString(char* p, int n) {

	p = (char*)malloc(sizeof(char) * n);

}
int main() {
	int n = 100;
	char* cp = NULL;
	GetString(cp, n);
	strcpy(cp, "hello");
	printf("%s", cp);
}

我们看这段代码,"hello"究竟能不能复制成功,答案是不能的,程序会崩溃,我们通过画图将程序走一遍

现在我们将代码修改一下,就可以将"hello"复制成功,有两种方法:

1)第一种方法:返回p变量,代码修改如下:

char* GetString(char* p,int n)
{
	p = (char*)malloc(sizeof(char) * n);
	return p;
}
	int main() {
		int n = 100;
		char* cp = NULL;
		cp=GetString(cp, n);
		strcpy(cp, "hello");
		printf("%s", cp);
}

我们通过画图将程序走一遍:

 2)第二种方法:不改变返回值的类型,而是通过改变参数来实现:

void GetString(char* *p, int n) {

	*p = (char*)malloc(sizeof(char) * n);

}
int main() {
	int n = 100;
	char* cp = NULL;
	GetString(&cp, n);
	strcpy(cp, "hello");
	printf("%s", cp);
}

我们通过画图将程序走一遍:

注意:上述代码都没有进行堆内存的释放,我们在写代码时一定要加上堆内存释放

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡蓝色的经典

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值