从底层来看函数的调用和返回
目录
- 一、引言
- 二、参数和局部变量的实现
- 2.1局部变量
- 2.2参数---形参和实参
- 2.3编译器是如何实现局部变量和参数的
一、引言
学c语言到现在,用了这么久的函数,可是我们为什么要使用函数呢?
其实就是为了重用一段代码。使用函数,我们可以输入不同的值,通过返回值来得到结果。
相关概念:
在汇编语言中,使用指令"call"和"ret"通过改变PC(程序计数器)的值来改变执行顺序
在这个过程中,也涉及到了数据的移动,像参数和返回值
当然程序内部,还有一些局部变量
二、参数和局部变量的实现
2.1局部变量
问题:变量可以取相同的名字吗?
有时可以,取决于情况
为什么呢?
因为编译器会将相同名字的变量映射到不同的地址。
例子
#include<stdio.h>
int first;
int second;//定义了一个全局的变量second
void callee(int first){int second;//定义了一个局部的变量secondsecond=1;first=2;printf("callee:first=%d,second=%d\n",first,second);printf("address of second:%#x\n\n",&second);
}
int main(){first=1;second=2;callee(first);printf("caller:first=%d,second=%d\n",first,second);printf("address of second:%#x\n",&second);return 0;
}
运行结果:
callee:first=2,second=1
address of second:0x61fed8caller:first=1,second=2
address of second:0x405068
通过这个例子,我们发现:
1.变量占用内存
2.编译器通过将相同名称的变量映射到不同的地址以实现作用域。
2.2参数—形参和实参
首先思考一个问题,形参和实参在内存中是共用同一块地址吗?也就是说,形参和实参的地址相同吗?
答案是否定的,形参和实参的地址不同。
可以通过一个小例子测试一下:
#include<stdio.h>
void callee(int formal_parameter){printf("address of second:%#x\n\n",&formal_parameter);
}
int main(){int actual_parameter=1;printf("address of second:%#x\n",&actual_parameter);callee(actual_parameter);//传入的实参的值return 0;
}
运行结果:
address of second:0x61fefc
address of second:0x61fee0
也就是说,编译器会为函数中的形参重新分配一个地址
那么为什么要这样设计:
这允许实际参数不受干扰,也就是说,不管我怎么修改我形参中的值,我实参都不会改变,保护了实参。
按值传递
–这允许实际参数保持不受干扰
通过引用
–C语言不支持引用调用,但是它的&和*操作符很容易达到相同的效果。相关内容可以查看C语言中指针传参
2.3编译器是如何实现局部变量和参数的
先看一个递归的例子
#include<stdio.h>
void callee(int n){printf("Function calls:%d(0x%08x)\n",n,&n);if (n==0) {printf("Function returns:%d(0x%08x)\n",n,&n);return;}callee(n-1);printf("Function returns:%d(0x%08x)\n",n,&n);
}
int main(int argc,char *argv[]){int n=5;callee(n);return 0;
}
运行结果:
Function calls:5(0x0061fee0)
Function calls:4(0x0061fec0)
Function calls:3(0x0061fea0)
Function calls:2(0x0061fe80)
Function calls:1(0x0061fe60)
Function calls:0(0x0061fe40)
Function returns:0(0x0061fe40)
Function returns:1(0x0061fe60)
Function returns:2(0x0061fe80)
Function returns:3(0x0061fea0)
Function returns:4(0x0061fec0)
Function returns:5(0x0061fee0)
在每次调用中,都需要创建一个本地变量n。思考一个问题,编译器怎么知道这个函数需要调用多少次呢?
编译器无法在程序运行完之前确定,所以只能在运行时动态分配。
这样做的缺点就是程序运行时性能会降低。
那编译器是怎么具体实现的呢?
因为编译器不知道它需要动态地分配多少变量,所以它保留了大量的空间来进行扩展。
堆栈:
堆栈是存储内存的一个特殊区域(用来存储每个函数创建的临时变量)
随着函数Push和Pop变量,栈也相应的增长和缩小。
从底层来看函数的调用和返回相关推荐
- python函数+定义+调用+多返回值+匿名函数+lambda+高级函数(reduce、map、filter)
python函数+定义+调用+多返回值+匿名函数+lambda+高级函数(reduce.map.filter) Python 中函数的应用非常广泛,比如 input() .print().range( ...
- python怎么调用函数的返回值类型,10、Python基础之函数的调用与返回值
一.函数参数 1.1 不定长参数 当我们定义函数时,可能需要定义一个函数能处理比当初声明时更多的参数,这些参数叫做不定长参数. 我们可以在形参前面加上一个 * ,这样这个形参就可以获取所有的实参,它将 ...
- vue函数如何调用其他函数?_编程|如何简单理解函数的传参、返回、调用
1 函数内部变量的局部性 在一个函数中定义的变量(包括实参),其作用域仅限于定义它的函数中,在其它的函数不能使用,这种变量称为"局部变量". 局部变量的作用域:函数内部声明和定义的 ...
- c语言 中断 局部变量 not allocated,C语言(函数)调用过程(略译)
C语言(函数)调用过程 Introduction A calling sequence is the conventional sequence of instructions that call a ...
- mysql 释放结果结_mysql_free_result() 函数释放结果内存,返回的数据只有布尔类型( )。...
[其它]实验三 函数的调用和返回 [单选题]ysql_free_result($result) 函数中的参数,可以是( )数据. [单选题]LTE的物理小区标识(PCI)有多少个 [单选题]PHP的各 ...
- python函数调用位置_python函数定义,调用,传参,位置参数及关键字参数,返回值
使用函数是真正开始编程的第一步,函数y=f(x)我们并不陌生,对x进行一顿操作得到一个值y.给不同的x,进行相同的操作,得到相应的y值. 程序层面函数是执行特定任务的一段代码,将一段代码定义成函数并为 ...
- androidstudio调用系统相机为什么resultcode一直返回0_函数递归调用?看这文就够了...
作者 | Cooper Song 责编 | Elle 出品 | 程序人生(ID:coder_life) 我猜,大多数程序员第一次接触函数的递归调用都是在算斐波那契数列某项值的时候,这是函数递归调用最常 ...
- Python基础day04【函数(定义与调用、文档说明、传参函数、全局变量、返回值、嵌套调用)】
视频.源码.课件.软件.笔记:超全面Python基础入门教程[十天课程]博客笔记汇总表[黑马程序员] Python基础day04[字典] 目录 3.函数 函数的定义和调用 函数定义 PEP8规范 ...
- Python中的函数(调用、参数、返回值、变量的作用域)
一.函数的调用 代码块一: def hello():print('hello1')print('hello2')print('hello3') hello() 示例一及运行结果: 代码块二: def ...
最新文章
- 重新认识vue之事件阻止冒泡
- shell变量设置与显示
- 使用 mysql workbench 建议
- java开心农场安卓_开心农场之田园日记
- reactjs快速如梦_帮助您理解和创建ReactJS应用的快速指南
- c语言建立动态链表ppt,C语言链表讲解.ppt
- 数学 —— 计算几何 —— 平面分割问题
- 未能加载文件或程序集“Oracle.DataAccess”或它的某一个依赖项。试图加载格式不正确的程序。...
- word2010添加b5纸张大小_【仁美文化】散文:薄如纸张
- Linux下编译环境及Makefile的学习笔记
- 【Luat-esp32c3】4.3 文件系统——加载jpeg图片并拆包
- 国防科大计算机学院贾焰,博士群体竞风流——记国防科大教员队伍的变化
- 大数据开发 电脑内存大小
- 数据结构-栈(栈的C语言实现)
- 计算机音乐谱童话镇,《童话镇》歌曲简谱
- FTP 获取远程目录列表返回421错误
- 人机交互设计(HCI)的七原则
- SEO,什么是SEO
- 【工业大数据】张洁教授现场剖析制造业大数据制造的思考与实践
- python爬取百度地图数据_Python利用百度地图爬取商家信息
热门文章
- tensorflow之exponential_decay
- 深度学习自学(六):Android人脸检测环境配置等相关问题
- windows10(专业版和家庭版)---禁止自动更新系统
- 电脑ip地址设置_关于路由器动态IP如何设置教程
- apache2 安装时报错 ServerRoot must be a valid directory
- 如何查看Android项目的gradle版本和路径
- Python判断字符类型
- php调用rpc,AMFPHP php远程调用(RPC, Remote Procedure Call)工具 快速入门教程_PHP教程
- Matlab重建信号实验总结,实验三信号采样与重建(实验报告).doc
- python opencv识别点个数_python+OpenCV 特征点检测