【C语言】关于函数返回栈空间地址问题

1.栈区的特点

我在 栈的介绍 这篇文章中讲过。

            栈,客栈,字面意思是存储货物或供旅客住宿的地方。

所以你借用了人家的房间,出去以后要还回去。这就是栈的特点。
当然,这些说法是为了帮助我们记忆的。

计算机领域里,

            栈区的特点是在上面创建的变量出了作用域就销毁,还给系统了。
            就是这个特点出现了很多典型的错误

2.典型的返回栈空间地址出现的问题

2.1 例子1

我们来看看下面这一段代码

int* Test()
{
	int a = 10;
	return &a;
}
int main()
{
	int* p = Test();
	printf("%d ",*p);
	return 0;
}

这段代码是想返回a的地址,然后用指针接收它,最后打印出来10。

但是,在执行函数时,函数内部的局部变量的存储单元是在栈上创建的,
当函数执行结束时,这些局部变量的存储单元会自动销毁,还给系统了。

所以,这个Test函数,它实际上是返回了一个野指针

             我们运行这段代码,会发现它还是会打印10

编译器报警告:
在这里插入图片描述

                返回局部变量或临时变量的地址:a

是不是不用说不管警告的话这样写代码也可以呢?

                有一句话说的好:透过现象看本质

我们在这段代码的基础上随便加一行代码:
在这里插入图片描述
你看,结果变了。

                      讲一个通俗易懂的理解

在这里插入图片描述
在这里插入图片描述

 总结就是,即使某一个函数执行完后,它被销毁,还给操作系统空间了。
 但是函数里面的内容可能没有被改。你要打印这个内容,也可以打印。
 但是当你在写其他代码的过程中,可能会向系统申请空间,申请的这个空间
 可能就是那个刚才栈区的空间,你一使用他,就会影响那个那个函数内容的值。

所以,不在乎警告强行这样写代码是非常危险的事情

解决方法就是加个static,把这个局部变量放在静态区

int* Test()
{
	static int a = 10;
	return &a;
}
int main()
{
	int* p = Test();
	printf("透过现象看本质\n");
	printf("%d ",*p);//10
	return 0;
}
    静态区的数据直到程序结束才销毁,所以a的值就是函数执行完毕也不会变

2. 2 例子2

char* GetMemory(void)
{
	 char p[] = "hello world";
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

int main()
{

	Test();
	return 0;
}

运行这段代码,它连给你警告的机会都没有。
直接乱码。
在这里插入图片描述

                 加个static把它放在静态区就解决了
char* GetMemory(void)
{
    static char p[] = "hello world";
	return p;
}

2.3例子3(变量存放到寄存器里面)

int Test()
{
	int a = 10;
	return a;
}
int main()
{
	int b = 0;
	b = Test();
	printf("%d", b);//运行这段代码,正常运行,打印10,无任何错误和警告?为什么?
	//a不是局部变量吗?出了函数不久被销毁了吗?为什么连警告都没有?
	return 0;
}
          此时Test函数里面的变量a是局部变量,为什么被销毁了调用函数,却没有被警告?
          我们简单理解一下就行,在这里不做深入研究

在这里插入图片描述

3.总结

1.实际上普通的局部变量是在栈区分配空间的,
栈区的特点是在上面创建的变量出了作用域就销毁。
2.但是被static修饰的变量存放在数据段(静态区),
数据段的特点是在上面创建的变量,直到程序结束才销毁
3.局部变量的值会放到寄存器里面,由寄存器传递。注意,仅仅是值,不是地址。
这是跟例子1和例子2的区别。

在后续的文章中我会讲到关于 栈区 堆区 静态区 的区别。
欢迎关注!
如有讲的不对的地方,欢迎指出,共同学习!

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

有心栽花无心插柳

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

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

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

打赏作者

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

抵扣说明:

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

余额充值