C语言return返回值深入理解
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寄存器,但是像这样在栈上开辟出来临时存储数据的单元,只要调用函数结束,就会释放掉里面的数据,因此虽然返回了一个指针,指针指向的数据却已经被系统销毁了,这就导致返回的指针指向不可预知的数据。
C语言return返回值深入理解的更多相关文章
- 关于ExecuteNonQuery执行存储过程的返回值 、、实例讲解存储过程的返回值与传出参数、、、C#获取存储过程的 Return返回值和Output输出参数值
关于ExecuteNonQuery执行存储过程的返回值 用到过ExecuteNonQuery()函数的朋友们在开发的时候肯定这么用过. if(cmd.ExecuteNonQuery("xxx ...
- C# 调用存储过程操作 OUTPUT参数和Return返回值
本文转载:http://www.cnblogs.com/libingql/archive/2010/05/02/1726104.html 存储过程是存放在数据库服务器上的预先编译好的sql语句.使用存 ...
- MSSQL - 存储过程Return返回值
1.存储过程中不使用外部参数. 存储过程: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ========================== ...
- C#获取存储过程的 Return返回值和Output输出参数值
1.获取Return返回值 程序代码 //存储过程//Create PROCEDURE MYSQL// @a int,// @b int//AS// return @a + ...
- return 返回值
# ### return 返回值 """ (1) return + 数据类型 : 将这个数据弹到函数的调用处,后面除了可以接六大标准数据类型之外,还可以返回类 对象 函数 ...
- 用jquery的ajax方法获取return返回值的正确姿势
如果jquery中,想要获取ajax的return返回值,必须注意两方面,ajax的同步异步问题,在ajax方法里面还是外面进行return返回值. 下面列举了三种写法,如果想成功获取到返回值,参考第 ...
- return 返回值的用法
#coding:utf-8 # (1)把数据返回到函数调用处 def func(): # return 1 # return "aaabb" return [1,2,3,4] re ...
- return 返回值的问题
def yue(): print("1. 打开手机") print("2. 打开陌陌") print("3. 找个漂亮的小姐姐") prin ...
- 用jquery的ajax方法获取不到return返回值
如果jquery中,获取不到ajax返回值. 两个错误写法会导致这种情况:1.ajax未用同步 2.在ajax方法中直接return返回值. 下面列举了三种写法,如果想成功获取到返回值,参考第三种写法 ...
随机推荐
- AtCoder刷题记录
构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...
- Excel 截取字符,判断县区 城市。
https://jingyan.baidu.com/article/624e7459aa90e434e8ba5a8a.html https://jingyan.baidu.com/article/9f ...
- @RequestBody的使用
一.说明 首先@RequestBody需要接的参数是一个string化的json,这里直接使用JSON.stringify(json)这个方法来转化 其次@RequestBody,从名称上来看也就是说 ...
- web程序设计关于我们
项目名称 福大咸鱼市场 开发团队 项目板块 负责人 美工 黄鸿杰 后端 胡继文 前端 葛家灿 联系方式:1175204449@qq.com
- What is the difference between UNION and UNION ALL?
What is the difference between UNION and UNION ALL? UNION removes duplicate records (where all colum ...
- List和数组的互转
list转数组: /要转换的list集合 List<String> testList = new ArrayList<String>(){{add("aa" ...
- Microsoft.Owin 使用 文件服务
添加引用: <package id="Microsoft.Owin" version="4.0.1" targetFramework="net4 ...
- MySQL可传输表空间:将一个表从一个实例拷贝到另一个实例
MySQL版本:5.7.23 1.在源实例上,创建一个表(如果不存在): mysql> USE abce; mysql> CREATE TABLE t(c1 INT) ENGINE=Inn ...
- parquet 简介(转)
原文 Parquet 列式存储格式 面向分析型业务的列式存储格式 由 Twitter 和 Cloudera 合作开发,2015 年 5 月从 Apache 的孵化器里毕业成为 Apache 顶级项目 ...
- 在线visio软件,在线流程图软件,在线绘图、在线画图
1. https://www.bullmind.com/ 推荐bullmind的在线visio软件,一种低成本的Visio替代品.bullmind是基于 网络的绘图工具,具有出色图表功能.您可以使用b ...