关于动态申请内存的动机

在c语言中,对于malloc();realloc();calloc();这些动态申请内存的函数,想必大家都不陌生了。但是为什么要动态申请呢。什么情况下需要申请内存呢?? 我觉得可能有下面几个原因,【当然纯属个人总结。不对或者不全面欢迎指正】。
关于申请内存的动机:
1、使得指针有具体的对象,并且该对象的内容是允许修改的。

这一层面的功能是可以用数组来代替的。即下面的这个语句:

char *str=(char*)malloc(20);

在一定程度上相当于:

char arr[20];
char *str=arr;//str指向arr

但是区别是前者的内存是在堆上建立的,除非free()/delete()释放
,否则内存会泄露。但是后者是利用的栈内存,当超出变量的作用范围之后,内存自动被撤销。【这一点区别涉及到了第二点动机,稍后再详谈。】

现在我们知道了如果单纯是为了申请一块可以利用的内存给指针,同时该内存的内容允许通过指针来改变,那么有两种方法:a、让指针指向一个定义好的数组,b、是直接申请动态内存。
因为这两种方法在这一层面的功能是一样的。请注意,我特别提出了该内存的内容允许通过指针来改变,这呼应了我刚才在第一点的标题说到的“该对象的内容是允许修改的”,之所以我要这么强调这一点,因为这是很关键的。
试想下,如果让你用指针指向字符串“Hello World”,有几种方式呢。刚刚讲的这两种方式都是可以的。但是有人会提出“更简单的”,认为可以用语句

char *str="Hello World";

没错,用这种方式是可以让指针str指向字符串的。但是”Hello World”是位于静态存储区的,不允许通过指针对其内容进行修改。即

char *str="Hello World";
str[0]='h';//该句运行出错。

所以我们就知道了,如果要修改对象的内容的话,第一种方式行不通的,那么我们剩下的方法还是只有上面说的两种老方法,一种是先建立一个数组,数组内容为“Hello World”,然后将str指向该数组地址。还有一种就是,申请动态内存,即

//方式1,定义数组,让指针指向数组
char arr[20]=“Hello World”;
char *str=arr;
str[0]='h';//合法
//方式2,申请动态内存
char *str=(char*)malloc(20);
strcpy(str,"Hello World");
str[0]='h';//也合法

关于这第一点动机,我就讲这么多。

2、如果要在子函数里面返回指针的话,最好用动态申请内存的方式来进行。

如果你不信,偏偏用下面这种方式进行,该方式是返回的指针指向的内容位于栈内存,不是堆。

#include<stdio.h>
#include<string.h>
char* fun();
int main()
{
    char *str=NULL;
    str=fun();
    printf("%s",str);
}
char* fun()
{

    char p[]="Hello World";//p指向的内容位于栈,
    return p;
}

运行结果为乱码:
这里写图片描述

这是因为栈内存在超出变量范围后会被回收的,所以p原本指向的是字符串”Hello World”,但是这是局限于子函数的范围内。p的内容赋值给str后,子函数的范围失效了,所以原本p指向的内容现在就不是字符串了,printf打印出来的就是乱码了。

下面这张是在子函数里面,p的指向的内存,内容确实是字符串。
这里写图片描述

但是程序运行到了主函数printf(),原来的内存内容却发生变化了,
这里写图片描述

所以可以看到,返回指向栈内存的指针是会发生错误的。
当你想要返回指针时,就应该想起申请动态内存。因为堆上申请的内存不会自动消失,必须要自己free()才能释放。
如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* fun1();
int main()
{
    char *str=NULL;
    str=fun1();
    printf("%s",str);
    free(str);//释放内存,否则会出现内存泄漏。
}
char* fun1()
{

    char *p=(char*)malloc(20);//指针指向的内容是用的堆内存
    strcpy(p,"Hello World");
    return p;
}

运行结果正如我们预料的。
这里写图片描述
至于内存的变化,自己一步步调试可以看到,str和p的内容都是一样的,所指的内容在free()之前都是字符串”Hello World”,在释放内存后才成了乱码。

当然,还有其他的一些动机。像直接定义一个长度固定的数组,有时候会白白浪费内存,因为真正用到的可能没有那么多。所以申请动态内存此时也是不错的选择。

综上所述,就是我理解的几种申请动态内存的动机,如果以后遇到了这几种情况,想一想是不是这时候需要申请动态内存了。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值