函数 栈帧

函数

引用式声明(函数原型):简称声明,指定了函数的返回值类型、函数的接受参数类型,这些叫函数的签名。与变量相同,在函数声明时编译器不会为函数分配内存。函数的返回值类型在C99之前若不指明则默认隐式转换为为int类型,但在C99之后必须指明函数的返回值类型。

定义式声明:简称定义,提供了函数的具体实现。不同于变量的定义,函数在定义时不会被分配内存,在函数调用时候编译器在栈帧上为函数分配内存。相同函数可以有多个声明,但只能有一个定义。

形参表:函数在声明或定义时的参数,注意形参只是声明而非定义。形参表在函数声明时可省略形参标识符(形参名),但不能省略形参的数据类型

实参表:函数在调用时实际传入的值

函数调用:主调函数(主动调用其他函数的函数) 被调函数(被其他函数调用的函数) 函数的嵌套调用 函数的递归调用

形参只是声明而非定义

形参在函数调用时会被赋予实际参数的值,而不是独立存在的变量。

  1. 形参的性质:形参是函数定义中的参数,在函数被调用时用于接收传递给函数的实际参数的值。形参在函数定义时就已经确定了,它们的作用是接收参数值,而不是独立的变量。因此,形参在函数定义中只是参数的声明,用于说明函数接收的参数类型和名称,而不是独立的变量定义。

  2. 形参和实参的关系:在函数调用时,实际参数的值会被传递给形参,形成了形参和实参的对应关系。形参会在函数执行期间使用实参的值,但形参本身并不是独立的变量,它们不会在函数调用之前分配内存空间或提供初始值。

  3. 形参在函数调用时赋值:当函数被调用时,实际参数的值会被赋给形参,形成了形参和实参之间的对应关系。形参在函数执行期间会被视为局部变量,但它们的值是由函数调用时的实际参数决定的,而不是在函数定义时确定的。

因此,形参在函数定义中只是参数的声明,用于说明函数接收的参数类型和名称,而不是独立的变量定义。形参的特殊性质使得它们只能被视为声明而不是定义。

栈帧

栈帧,也称为活动记录、调用帧或过程帧,是在函数调用时在函数调用栈中分配的一块内存区域,用于存储函数的局部变量、参数值、函数返回地址以及其他与函数调用相关的信息。

每当函数被调用时,都会在栈上创建一个新的栈帧,栈帧在函数调用结束后会被销毁。栈帧的创建和销毁都是由编译器和执行环境来管理的。

典型的栈帧结构包括以下几个部分:

  1. 局部变量区:用于存储函数内部声明的局部变量,这些变量在函数调用时被创建,在函数返回时被销毁。

  2. 参数区:用于存储函数调用时传递的参数值。

  3. 返回地址:指向调用该函数的指令地址,函数执行完毕后会返回到该地址继续执行。

  4. 旧的基址指针:指向调用该函数的上一个栈帧的基址指针,用于在函数返回时恢复上一个栈帧。

  5. 其他辅助信息:如编译器生成的临时变量、寄存器保存等。

栈帧的存在使得函数调用能够有效地管理函数的局部数据和调用关系。每个函数调用都会在栈上创建一个新的栈帧,形成一条栈链,函数的局部变量和参数在各自的栈帧中进行存储,保证了函数调用之间的隔离性。

从栈帧角度看函数调用

基址指针,是在函数调用时用于帮助在栈上定位局部变量和参数的指针。基址指针指向当前函数栈帧的基址,也就是栈帧中局部变量和参数的起始地址。

在一些体系结构中,特别是x86架构下的C语言编程中,通常使用基址指针和栈指针来进行栈操作。栈指针指向当前栈顶,而基址指针则通常指向当前栈帧的底部。

基址指针的主要作用是:

  1. 定位局部变量和参数:通过基址指针加上偏移量来访问函数的局部变量和参数。
  2. 帮助在函数调用中保存和恢复现场:基址指针在函数调用时被保存在当前函数栈帧中,在函数返回时用于恢复上一个函数栈帧的状态,以便程序能够正确地返回到调用函数的位置。

在函数调用过程中,基址指针和栈指针的变化和协作是确保函数调用能够正确执行的关键。

当一个函数被调用时,会发生以下步骤:

  1. 保存上一个栈帧的状态:调用函数时,当前函数的栈帧会被压入调用栈,此时需要保存上一个栈帧的状态。这包括保存上一个栈帧的基址指针(旧的基址指针)和返回地址。这些信息保存在当前栈帧中以便在函数返回时能够恢复到上一个栈帧的状态。

  2. 分配当前函数的栈帧:为当前函数调用分配一个新的栈帧,包括存储局部变量、参数和其他与函数调用相关的信息。

  3. 传递参数:将调用函数时传递的参数值复制到当前函数的栈帧中的参数区域。

  4. 执行函数体:开始执行被调用函数的代码,包括对局部变量的操作和执行其他语句。

  5. 返回地址更新:当遇到函数返回语句时,执行流程会返回到调用该函数的指令处。这时会使用保存在当前栈帧中的返回地址,跳转到调用处继续执行。

  6. 恢复上一个栈帧状态:在函数返回时,需要恢复上一个栈帧的状态,包括恢复旧的基址指针和返回地址,以便继续执行上一个函数的代码。

  7. 释放当前栈帧:当前函数执行完毕后,它的栈帧会被销毁,释放栈上的内存空间。

这样,函数的调用就完成了。整个过程中,栈帧的切换和状态保存使得程序能够正确地管理函数调用关系,并保证函数调用的正确执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/687036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DNS服务正反解析

1.正向解析 1.配置基本 1.1防火墙配置 二者都要关闭 setenforce 0 systemctl stop firewalld #关闭防火墙 yum install bind -y #下载bind软件 客户端可以不用下 1.2服务端配置静态ip, ip a 查看网卡 nmcli c modify ens33 ipv4.method manual ipv4.addresses …

OpenAI发布Sora模型,可根据文字生成逼真AI视频

早在2022年11月30日,OpenAI第一次发布人工智能聊天机器人ChatGPT,随后在全世界掀起了人工智能狂潮,颠覆了一个又一个行业。在过去的一年多的时间里,chatGPT的强大功能改变了越来越多人的工作和生活方式,成为了世界上用…

Python教程(26)——Python迭代器和生成器详解

迭代器 Python中的迭代器是一种对象,它可以迭代(遍历)一个可迭代对象(比如列表、元组或字符串)的元素。迭代器用于实现迭代器协议,即包含 __iter__() 方法和 __next__() 方法。 迭代器的工作原理是每次调…

vue watch监听

在 Vue.js 中,watch 是一个对象,用于观察和响应 Vue 实例上的数据变化。当被监视的属性发生变化时,watch 里的回调函数将被调用。 (vue2)官方文档:计算属性和侦听器 — Vue.js (vuejs.org) 下面是一个简单…

数据的力量:构筑现代大型网站之数据库基础与应用

目录 数据库基础知识--前言 大型网站架构特点 DBA数据库管理员 什么是数据? 数据存储 什么是数据库 数据表的概念 为什么需要mysql这样的数据库管理工具?★ DBMS 收费数据库与免费数据库 运维和数据库 开发与运维的不同阶段 数据库类别 数据库具体应用…

【机器学习笔记】11 支持向量机

支 持 向 量 机 ( Support Vector Machine,SVM ) 支 持 向 量 机 是 一 类 按 监 督 学 习 ( supervisedlearning)方式对数据进行二元分类的广义线性分类器(generalized linear classifier),其…

C#安装CommunityToolkit.Mvvm依赖

这里需要有一定C#基础, 首先找到右边的解决方案,右键依赖项 然后选择nuget管理 这里给大家扩展一下nuget的国内源(https://nuget.cdn.azure.cn/v3/index.json) 然后搜自己想要的依赖性,比如CommunityToolkit.Mvvm 再点…

学习Android的第十四天

目录 Android DatePicker 日期选择器 DatePicker 属性 和 事件 DatePicker 事件 获得 DatePicker 的值 Android TimePicker 时间选择器 TimePicker 属性 TimePicker 事件 获得 TimePicker 的值 Android CalendarView 日历视图 CalendarView 属性 CalendarView 事件 …

Linux超详细笔记

文章目录 Linux学习笔记操作系统Linux初识Linux的诞生Linux内核Linux发行版 虚拟机VMware安装远程连接Linux系统FinalShellFinalShell连接Linux WSL配置UbuntuLinux常用命令1.入门2.ls命令cd命令3.pwd命令4.相对路径和绝对路径5.mkdir命令6.文件操作命令(1&#xff…

vue打包优化,webpack的8大配置方案

vue-cli 生成的项目通常集成Webpack ,在打包的时候,需要webpack来做一些事情。这里我们希望它可以压缩代码体积,提高运行效率。 文章目录 (1)代码压缩:(2)图片压缩:&…

[AIGC] Kafka 消费者的实现原理

在 Kafka 中,消费者通过订阅主题来消费数据。每个消费者都属于一个消费者组,消费者组中的多个消费者可以共同消费一个主题,实现分布式消费。每个消费者都会维护自己的偏移量,用于记录已经读取到的消息位置。消费者可以选择手动提交…

17.3.2.9 像素处理与内存处理之比较

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 通过第17.3.2.1节到第17.3.2.8节,相信读者对通过锁定内存来处理图像有了一定认识。与第17.3.1节相比较,可以…

代码随想录day28 Java版

134. 加油站 使用三个变量total、cur和start来记录总剩余油量、当前剩余油量和起始加油站的索引。在遍历加油站数组的过程中,不断更新cur为当前剩余油量,并根据cur的值判断是否需要更换起始加油站。 如果cur小于0,说明从当前起点到当前加油…

课时34:脚本交互_基础知识_子shell基础

2.1.2 子shell基础 学习目标 这一节,我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 场景 之前我们对于环境变量在多个shell环境中的应用进行了学习,那种操作量比较大。对于一些临时性的场景,我们在临时性的环境中&#xff…

程序的控制结构详解

程序的控制结构 结构化程序设计方法的基础 在计算机刚出现的早期,它的价格昂贵、内存很小、速度慢。程序员为了在很小的内存中解决大量的科学计算问题,并为了节省昂贵的CPU机时费,不得不使用巧妙的手段和技术,手工编写各种高效的…

目标检测算法之YOLOv5的应用实例(零售业库存管理、无人机航拍分析、工业自动化领域应用的详解)

1.YOLOv5在"零售业库存管理"领域的应用 在零售业库存管理中,YOLOv5可以帮助自动化商品识别和库存盘点过程。通过使用深度学习模型来实时识别货架上的商品,零售商可以更高效地管理库存,减少人工盘点的时间和成本。以下是一个使用YOLOv5进行商品识别的Python脚本示…

[office] Excel中函数进行计算两个日期参数差值的方法 #职场发展#学习方法#媒体

Excel中函数进行计算两个日期参数差值的方法 在excel使用中,如果想计算两个日期参数的差值,该用什么函数和如何使用呢?今天,小编就教大家在Excel中函数进行计算两个日期参数差值的方法。 Excel中函数进行计算两个日期参数差值的步骤 在excel…

javascript中的prototype;javascript中的原型链

文章目录 深入理解JavaScript原型链1. 什么是原型链?2. 原型链的结构3. 如何访问原型链?4. 示例演示原型链5. 原型链与继承6. 实际应用场景 深入理解JavaScript原型链 1. 什么是原型链? 在JavaScript中,每个对象都有一个原型&am…

【python】网络爬虫与信息提取--正则表达式

一、正则表达式 正则表达式是用来简洁表达一组字符串的表达式。是通用的字符串表达框架,简洁表达一组字符串的表达式,针对字符串表达“简洁”和“特征”思想的工具,判断某字符串的特征归属。 用处:表达文本类型的特征;…

永久禁止windows自动更新方法

文章目录 前言一、打开本地组策略编辑器二、禁用windows更新总结 前言 每次打开电脑,右下角就会弹出设备更新提示,看着令人烦恼,并且更新可能导致电脑设置发生改变甚至是卡顿,所以为了自己方便于是出了禁用电脑更新的办法&#x…