C语言使用return关键字返回函数值,可以很好对函数做封装,此处的疑问是:函数内部创建的变量都是局部变量,即私有的,作用域就在函数之内,为什么却可以把值传给调用函数?

解释这个问题还需要从C语言调用函数传参类比来说,C语言传参调用时,可以采用传值和传指针两种方式。

传值的形式:只是将参数值的拷贝传给函数,并非参数本体,如:

 int test_func(int i)
{
i++;
printf("Function i : %d\n", i);
return ;
} int main()
{
int a = ;
printf("Main Pre: %d\n", a);
test_func(a);
printf("Main Now: %d\n", a); return ;
}

传指针形式:直接传给函数的是变量的地址,由于被调函数在参数指针的作用域之内,此时直接改变变量的本体。

 int test_func(int *i)
{
(*i)++; //注意:++的优先级比*高
printf("Function i : %d\n", *i);
return ;
} int main()
{
int a = ;
printf("Main Pre: %d\n", a);
test_func(&a);
printf("Main Now: %d\n", a); return ;
}

同理,函数返回也有两种形式。

1、函数返回变量值

此时,返回变量值的方式与函数调用传值同样的道理,在函数结束返回时,将局部变量值拷贝给一个临时变量,然后将这个临时变量返回给调用函数。因此,即使局部变量在返回时已经释放内存,也不影响返回的变量值。

 int test_func()
{
int i = ;
printf("Function i : %d\n", i);
return i;
} int main()
{
int a = ;
a = test_func();
printf("Main Now: %d\n", a); return ;
}

从汇编的角度来看源代码:

由以上看出:返回变量值的时候,直接将局部变量的值传给了了寄存器eax,也就是说,函数返回以后,虽然局部变量已被释放,但是eax里面的还有一个值的拷贝。

2、函数返回地址

此时注意:C语言的指针操作,大部分都是直接对指针指向的变量直接操作,函数内部的变量和指针一般分配在栈上,而栈上的数据都是临时保存的,当函数返回时会自动释放掉,因此如果直接返回一个栈上的指针,返回的值将不可预知。

 int *test_func()
{
int local_data = ; printf("Function local_data : %d\n", local_data); return &local_data;
} int main()
{
int *main_data = NULL; main_data = test_func(); printf("Return data: %d\n", *main_data); return ;
}

从汇编语言角度查看源码:

由以上看出:返回指针的时候,用的是指令lea,这条指令的作用是,将[ebp-4](此单元对应的是变量local_data在栈上的数据存储位置)这个数据单元的地址传给eax寄存器,但是像这样在栈上开辟出来临时存储数据的单元,只要调用函数结束,就会释放掉里面的数据,因此虽然返回了一个指针,指针指向的数据却已经被系统销毁了,这就导致返回的指针指向不可预知的数据。

最新文章

  1. Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译
  2. VS2013的 Browser Link 引起的问题
  3. 电脑控制Android设备的软件——Total Control
  4. 基于HTML5的WebGL呈现A星算法的3D可视化
  5. Linux Shell 02 流程控制语句
  6. ActivityInfo taskAffinity
  7. myeclipse trial expired[转]
  8. Hash function
  9. nginx配置中文域名解析
  10. 创建git repo
  11. [置顶] ARM-Linux下WEB服务器Boa的移植、配置和运行测试
  12. centos6.5 搭建nginx1.6.0 +gridfs +mongodb2.4..10环境
  13. 织梦dedecms文章发布日期时间调用标签大全
  14. 将ADS1.2的工程迁移到KEIL上-基于2440
  15. 如何使用sourcetree 或 IDEA 自带的git合并代码?
  16. Arbiter 系统使用说明
  17. PL/SQL Block中对单引号进行转义
  18. CSS table-layout 属性
  19. 关于EF实体类的一点思考
  20. java爬取网页Unicode转UTF-8中文

热门文章

  1. 用于C# 的异步,持久的键值存储 Akavache 使用
  2. [RN] React Native 仿美团下拉筛选菜单控件
  3. mysql课外积累
  4. css选择指定元素
  5. arris1750 pandorabox安装bandwidthd之后带宽监控(nlbwmon)报资源不足
  6. WebDataBinder 学习顺序
  7. 【转】【Centos】Linux(Centos7)下搭建SVN服务器
  8. Java13新特性 -- 重新实现旧版套接字API
  9. Linux(CentOS)启动时自动执行脚本(rc.local)
  10. SpringMVC基本