详解C语言中return返回函数局部变量的问题
目录
- return返回栈区局部变量的指针
- return返回栈区局部的临时变量
- return只读数据段和static数据
这也就意味着,当函数结束调用的时候,函数中的局部变量实际上还是在的,只是函数原来的空间还给编译器(释放)了,也就是说函数中的局部变量是可以被编译器修改的。
虽然函数结束后空间还给了编译器,但是我们依然可以通过指针找到对应的局部变量的空间。
return返回栈区局部变量的指针 通过上面的分析,如果我们返回局部变量的指针,是不是可以直接找到这个局部变量呢?
返回了一个局部变量的指针,而恰好局部变量偏偏又在函数结束后销毁,但指针并没有被销毁,而是被返回,那也就是说,指针指向的正是一个被销毁了的对象。
比如下面的代码:
#include char* returnStr(){char p[] = "hello world!"; return p; }int main(){char* str; str = returnStr(); printf("%s\n", str); return 0; }
文章图片
可以看到原来p的空间已经被修改了,但是很奇怪,是谁进行的修改呢?
通过调试可以发现,当函数结束后,运行printf打印之前,str指向的空间中的字符串是在的:
文章图片
但是一运行printf打印操作,str指向的空间中的字符串就会被修改:
文章图片
这其实很好解释,因为printf本身也是一个函数,函数都是在栈区开辟的,而函数开辟的空间叫做栈帧,函数结束栈帧就还给了编译器:
文章图片
了解了这些,那是不是只要我们多建立几个函数栈帧,是不是就可以使returnStr的函数栈帧不被覆盖了?答案是肯定的:
#include char* fun6(){char p[] = "hello world"; return p; }char* fun5(){return fun6(); }char* fun4(){return fun5(); }char* fun3(){return fun4(); }char* fun2(){return fun3(); }char* fun1(){return fun2(); }char* fun(){return fun1(); }int main(){char* str; str = fun(); printf("%s\n", str); return 0; }
文章图片
文章图片
不过随着函数栈帧的逐渐增多,原来的fun6函数空间迟早也会被覆盖。
在函数体内定义的局部变量是有临时性的,当局部变量释放后随时都有可能会被修改,所以我们不能通过指针使用已经被释放的局部变量。
return返回栈区局部的临时变量 如果我们不返回指针,而是返回局部变量会怎么样呢?
按理来说局部变量也会被修改。
#includeint test(){ int a = 10; return a; }int main(){ int b = test(); printf("%d", b); }
文章图片
【详解C语言中return返回函数局部变量的问题】通过反汇编可以看到,局部变量a的值10通过寄存器交给了调用的b,所以即使局部变量a空间的10已经被修改,也不会影响b的内容:
文章图片
return只读数据段和static数据 如果返回只读字符串则不会被覆盖,因为数据不是在栈区,而是在静态区:
文章图片
同理如果将字符串用static修饰也是如此:
文章图片
另外,返回堆内的指针也是可以的。
到此这篇关于详解C语言中return返回函数局部变量的问题的文章就介绍到这了,更多相关C语言return返回函数局部变量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- 夜游宫|夜游宫 心语
- 跌跌撞撞奔向你|跌跌撞撞奔向你 第四章(你补英语,我补物理)
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- 子龙老师语录
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 【生信技能树】R语言练习题|【生信技能树】R语言练习题 - 中级
- 小学英语必考的10个知识点归纳,复习必备!
- 六步搭建ES6语法环境
- 一起来学习C语言的字符串转换函数
- C语言字符函数中的isalnum()和iscntrl()你都知道吗