深入理解内联函数(C语言)

news2025/3/16 6:39:31

目录

  • 1.什么是内联函数
  • 2.内联函数与宏
  • 3.编译器对内联函数的处理
  • 4.参考文献

1.什么是内联函数

很多人都会知道,可以将比较小的函数写成内联函数的形式,这样会节省函数调用的开销,具体是什么样的开销呢?
一个函数在执行过程中,如果需要调用其他函数,则一般会执行下面的过程。

  1. 保存当前函数现场
  2. 跳到调用函数执行
  3. 恢复当前函数现场
  4. 继续执行当前函数

一个C语言程序,在main()函数中对某些数据进行处理,运算结果暂时保存在R0寄存器中。接着调用另一个函数call_fun(),调用结束后,返回main()函数继续执行。如果我们在call_fun()函数中要用到R0寄存器,就会改变R0中的值,当我们返回main()中继续执行程序的时候,就会出现错误的计算。

处理办法很简单,就是在跳到call_fun()之前,先将R0中的值保存到对战中,调用结束后,再将其值取出来,这样就可以顺利地执行main()函数了。这就是所谓的现场保存和恢复。

对于一般的函数调用,当然没有什么问题,但如果需要调用的函数本来就很小(指令和数据都不多),这个时候如果频繁地调用,就会出现频繁地保存现场,恢复现场,降低了程序的执行效率,这个时候就可以将call_fun()改写为内联函数,简单高效。

2.内联函数与宏

内联函数和宏的功能差不多,为什么不直接定义一个宏,而去定义一个内联函数呢?二者又有什么不同呢?

与宏相比,内联函数具有以下优势。

  • 参数类型检查:内联函数具有宏的展开特性,但本质仍是函数,在编译过程中,编译器仍然可以对其进行参数检查,而宏不具备此功能。
  • 便于调试:函数支持丰富的断点调试功能,而宏定义不支持,这样便于软件的调试和开发。
  • 接口封装:有些内联函数可以用来封装一个接口,而宏并无此特性。

3.编译器对内联函数的处理

众所周知,并不是在函数前添加了inline关键字,程序在执行过程中就会乖乖执行内联展开,这与开发者和计算机都有关系。

而若要得知函数是否真正进行了内联展开,则需要深入底层,从汇编程序中得知。

尺有所短,寸有所长,内联函数也有缺点。内联函数会增大程序的体积,如果在一个文件中多次调用内联函数,多次展开,则整个函数的体积就会变大,降低了代码的执行效率。这与函数的设计初衷相悖(函数的作用之一就是提高代码的复用性)。

编译器在对内联函数做展开时,除了检测用户定义的内联函数是否有指针、循环、递归,还会在函数执行效率和函数调用开销之间进行权衡。一般来说,从程序员角度来说,主要考虑以下因素。

  • 函数体积小。
  • 函数体内无指针赋值、递归、循环等语句。
  • 调用频繁。

下面的例子,我们用一个简单的程序实现了某个数的阶乘。
在这里插入图片描述
我们封装了两个函数,都含有linline关键字,而从编译后的汇编程序可以看出,一个函数进行了内联展开,而另一个可能考虑到了函数并不是很精简,并未对其进行内联展开。

然后将优化等级调到了1,再看看结果:
在这里插入图片描述
可以看到,将两个函数都进行了内联展开。输出结果仍然是24,保持不变。

接下来我们使用GCC编译器提供的特性__attribute__来实现强制内联:
在这里插入图片描述
可以看到,此时即使关闭了优化等级,编译器还是对两个内联函数进行了内联展开。程序的运行结果也不会受影响。

此次我们采用了在线的编译工具,感觉还不错,喜欢的同学可以试试。
Compiler Explorer

4.参考文献

《嵌入式C语言自我修养》

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

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

相关文章

低利率之后如何选择?以日本养老金为例

天风证券认为,日本养老金资产配置行为具备的关键特征包括:海外资产占比上升、日元境内资产占比下降;权益类(包括境内和境外)占比上升,等等。 日本从1990年代开始陷入低增长、低通胀的局面,我们以…

解决win系统msvcp140.dll丢失的多种常用方法,亲测有效!

msvcp140.dll 是一个重要的Windows系统文件,属于Microsoft Visual C Redistributable runtime components的一部分,特别与Visual Studio 2015及之后版本编译的C应用程序相关联。这个动态链接库(DLL)文件包含了一系列C标准库的功能…

好用的window粘贴板

可以设置指定的快捷键,在需要使用最近复制的记录时快速的复用 -> Ditto。 选择Download即可 地址:Ditto clipboard manager (sourceforge.io)https://ditto-cp.sourceforge.io/

VUE3+Vite+vant4从零开始构建前端项目

VUE3Vitevant4从零开始构建前端项目 1. 环境准备Node.js 安装 2. Vite 构建项目3. 集成Vant41. 安装Vant 组件2. 引入组件3. 使用vant按钮组件 1. 环境准备 Node.js 安装 Node.js官网地址:https://nodejs.p2hp.com/ 下载最新的版本,下载文件为msi结尾的…

用本地大模型(llama3)进行数据分类标记|LLM 用例

001|背景 这是我最新发布的导航站点 https://aiwith.me 这个站点由于第一版数据来源于第三方,只有站点基础数据,没有对数据进行分类,最近站点上线了,主体框架都搭建完成了,这才有空去对数据做分类. 目前的…

Android kotlin协程

说明 可代替线程整异步可控制,灵活 (控制优先级,内存占用等)速度快 效率高有数量上限 使用 runBlocking 一般用于测试 不建议使用GlobalScope.launch 全局的 生命周期跟随application 不建议使用CoroutineScope(job) 用 基本使…

C结构详解

目录 1、结构模板 1. 建立结构声明 2. 定义结构变量 3. 访问结构成员 4. 初始化结构 声明结构数组 声明和初始化结构指针 1、结构模板 1. 建立结构声明 struct book{char title[MAXTITL];char author[MAXAUTL];float value; }; 该声明描述了一个又两个字符…

指北者智能音乐学习机隆重亮相广州国际乐器展

2024年5月23-26日广州国际乐器展览会在广交会展馆B区隆重开幕,本届展会开设5大展厅、50000平方米的主题展区,吸引了700多家国内外参展商参展,打造集展示、商贸、文化交流、文娱于一体的广阔平台。深圳市指北科技有限公司也携旗下品牌指北者智…

plt多子图设置

import matplotlib.pyplot as plt# 使用 subplots 函数创建一个 2x3 的子图网格 fig, axs plt.subplots(nrows2, ncols3, figsize(16, 10)) # 调整 figsize 来改变图像大小# 遍历每个子图,并绘制一些内容(这里只是简单的示例) for ax in ax…

leetcode230 二叉搜索树中第K小的元素

题目 给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。 示例 输入:root [5,3,6,2,4,null,null,1], k 3 输出:3 解析 这道题应该是能做出…

计算机网络-BGP概述

一、概述 到目前为止我们已经学习了静态路由、OSPF、RIP、IS-IS了,前面我们也了解到按照区域或者范围来分,路由协议可以划分为:IGP内部网关协议、EGP外部网关协议,而我们前面学习的动态路由都属于IGP的范畴. IGP是用于单一自治系统…

AI大模型探索之路-训练篇25:ChatGLM3微调实战-基于LLaMA-Factory微调改造企业级知识库

系列篇章💥 AI大模型探索之路-训练篇1:大语言模型微调基础认知 AI大模型探索之路-训练篇2:大语言模型预训练基础认知 AI大模型探索之路-训练篇3:大语言模型全景解读 AI大模型探索之路-训练篇4:大语言模型训练数据集概…

NetSuite Intercompany COGS科目设置问题

在22年底的NetSuite多公司功能串讲中,有一个题目是Intercompany COGS科目的设置问题。近期在项目上这个问题被密集讨论。为了方便分享,所以在此摘出来独立成文。有兴趣的同学也可以翻看之前的视频。 NetSuite知识会 第8谈 多公司功能串讲 NetSuite Inter…

性能测试--线程的监控

1.线程的状态 1.1.线程的5种状态 java的线程总共有5种状态,如下: * 新建:new 【新建之后不启用都是new】* 运行:runnable* 等待:waitting(无限期等待),timed waitting(限期等待)* 阻塞:blocked* 结束&am…

1.存储部分

1.Flash Memory--闪速存储器(注:U盘,SD卡就是闪存)在EEPROM基础上发展而来的,断电后也能保存信息,且可进行多次 快速擦除重写。注意:由于闪存需要先擦除再写入,因此闪存写的速度要比…

[less配置]vue2引入less

1、终端输入:npm install less less-loader --save-dev 2、在package.json查看是否安装less依赖 3、调用

Add object from object library 从对象库中添加内置器件

Add object from object library 从对象库中添加内置器件 正文正文 对于 Lumerical,有些时候我们在使用中,可能需要从 Object library 中添加器件,通常我们的做法是手动添加。如下图所示,我们添加一个 Directional Coupler 到我们的工程文件中: 但是这种操作方式不够智能…

基于附带Attention机制的seq2seq模型架构实现英译法的案例

模型架构 先上图 我们这里选用GRU来实现该任务,因此上图的十个方框框都是GRU块,如第二张图,放第一张图主要是强调编码器的输出是作用在解码器每一次输入的观点,具体的详细流程图将在代码实现部分给出。 编码阶段 1. 准备工作…

Element Plus (面向外卖编程)

Element介绍 使用流程 案例 Element介绍 是饿了么团队基于 Vue 3 研发的面向设计师和开发者的组件库,访问官网能使用到各种组件样式 组件:组成网页的部件,例如 超链接、按钮、图片、表格、表单、分页条等等。官网:https://…

AI多模态「六边形战士」,原创音乐、1分钟百页PPT、抖音爆款……

2024年AI行业最大的看点是什么? 那一定是多模态AI应用。 大模型发展到今天这个阶段,文本处理已经是各家大模型的必备技能了,对音频、视觉等多模态的理解和应用才是下一个阶段大模型比拼的赛道。 3.5研究测试:hujiaoai.cn 4研究测…