返回局部变量指针

一般我们都知道不能返回局部变量的指针,但很多人知道其然,不知道所以然,那么接下来我们分析一下,先看两段代码

/*test1.c*/

#include <stdio.h>

char* get_str()
{
    char str[] = {"hello"};
    return str;
}


int main()
{
    char* p = get_str();
    printf("%s/n", p);
    return 0;
}

 

====================

/*test2.c*/

#include <stdio.h>

char* get_str()
{
    char *str = {"hello"};
    return str;
}


int main()
{
    char* p = get_str();
    printf("%s/n", p);
    return 0;
}

 

test2.c运行是没有问题的,也可以打印出正确的值,而test1.c却是错误的,打印出来的值和预期的完全不一样。他们都是返回了局部变量的指针,为什么会有差异呢,我们仔细看代码,发现他们只有一个地方不一样,那就是test1.c 里面str是一个数组,test2.c里面str是一个指针。原因就在这,str指针,其值是一个常量,而常量是放在数据段里面的,即便函数返回了,数据段里面的常量数据也还会在,直到程序结束才会消失,所以我们可以打印出来。

而对于数组来说,它是一个局部变量,是放在栈里面的,函数返回之后,str指向的空间还是在的,如果我们打印出它的地址还是没有变。那么为什么内容会变掉呢,难道是系统会把栈中的数据清除,答案是否定的,因为这样做会消耗系统的资源,而且没有任何好处,下次用到这块内存还是会进行初始化的。打印出来的内容变掉是因为printf本身也是一个函数,也会进行参数的压栈,在压栈的过程中会把原来str指向的空间覆盖掉,也就改变了其中的值。如果我们在get_str之后,不调用任何函数并不创建新的局部变量(严格的说是不使栈继续往下增长),这个时候p指向的内容还是没变的。

下面是在帖子里看到的一些讲解:

1. 不能返回在函数内部的 "栈内存", 因为它在函数退出的时候会被自动销毁,这也是我们写函数定义局部变量而不担心其释放问题
2. 返回在函数内部申请的"堆内存",必须由用户自己控制该内存的释放,因为这点不好控制,容易被忘记,所以大多都给函数传递外部的指针进来. 如果你把它看作类似于 New 一样, 也好理解

典型的局部变量和内存分配,回收的问题
分配内存有两种方式,一种是在堆上分配,也就是malloc和new这两个东东,一个是用于C,一个是用于C++,在堆上分配的内存要用free和delete来释放
另一种分配内存的方式是在栈上分配,就比如char p[10],就会在栈上开辟十个字节的空间,在栈上分配的空间会在其作用域不存在时自动释放,比如你在一个函数中声明一个这样的变量,当这个函数退出时,这个变量所指向的空间会被收回;
所以你在子函数中声明一个char *变量,并用malloc分配空间后,并没有手动释放,那么在其它函数访问它就是合法的,但程序结束时就手动释放它,不然的话,就有内存泄漏的问题
你在子函数中声明一个数组,它会在栈上分配空间,当此子函数结束后,些内存中的内容会被自动回收
所以你在调用的函数中就引用了一个被释放了的地址,当然要出错了

最好还想说一点的是:声明一个全局变量,它会被自动初始化(好像是编译器做的工作),而一个局部变量是不会被自动初始化;而字符串常量和宏定义的东东在被编译时好像已被放在了文本段(请参阅可执行文件的结构)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值