C语言基础-内联函数在头文件中的定义

文章目录

    • 前言
    • inline关键字
      • 优点
      • 缺点
      • 使用注意
    • 头文件中定义函数
    • 内联函数在头文件中的定义
    • 总结

前言

在软件开发过程中,大家可能很少会遇到inline关键字,也可能很少见到头文件中定义函数体。没有用过不代表不能了解,菜就多练!哈哈哈~本文学习一下inline关键字,及在头文件中的使用。

inline关键字

在高质量C++/C 编程指南中,有很好的说明inline关键字:inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。意思就是说应该在函数定义时使用inline关键字来指示该函数为内联函数,在声明时没有必要再使用inline

优点

使用inline关键的优点:

1.提高性能:内联函数的主要目的是减少函数调用的开销,包括传递参数、保存和恢复现场、跳转回原地址等。当函数非常小并且频繁调用时,将其内联化可以显著提升程序的运行速度。

2.提高代码可读性:对于简单的小函数,内联后可以避免函数调用堆栈,使得代码逻辑更加直观,特别是在嵌入式系统或者对性能要求极高的场景下。

缺点

1.代码膨胀:内联函数会导致最终生成的目标代码体积增大,尤其是在函数体较大或者函数被多次调用的情况下,可能导致存储空间占用增加以及可能影响内存管理(比如增加分页数量)。

2.不利于模块化和维护:内联函数的代码会分散到各个调用点,这可能使得代码更难以理解和维护,特别是当函数体发生变化时,所有包含此内联函数的调用点都需要重新编译。

3.限制了编译器优化:编译器在独立的函数中可以进行更多的优化,如循环展开、寄存器分配等,内联后可能会影响这些优化效果。

使用注意

有了上述优缺点,我们可以得到何时使用内联:

函数非常小并且频繁调用

以下情况不适合使用内联:

(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。

(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。

inline定义的函数一定会成为内联函数吗?答:不一定。编译器根据自身的优化策略判断是否真的进行内联处理

头文件中定义函数

大家一般的认知应该是函数在源文件中定义,头文件中声明。那为什么头文件中不建议定义函数?

如果一个头文件定义了一个函数,而该头文件又被多个源文件包含时,在预处理时头文件展开,每个文件都有了一个该函数的定义,因为编译时是分隔的,所以到链接时,将所有文件关联在一起时,发现每个包含了该头文件的文件中有一个相同函数的定义,编译器就会报出重定义的错误

所以在头文件中尽量不要进行函数的定义,只对其进行声明。否则如果有多个源文件链接时会报错

内联函数在头文件中的定义

回到本文标题,为什么内联函数要定义在头文件中?
inline函数(即内联函数)对编译器而言必须是可见的,以便能够在调用点展开该函数,与非inline函数不同的是,inline函数必须在调用该函数的每个文件中定义。(也就是所谓的代码膨胀

正因为如此,建议把inline函数的定义放到头文件中,在每个调用该inline函数的文件中包含该头文件。这种方法保证了每个inline函数只有一个定义,且程序员无需复制代码,并且不可能在程序的生命周期中引起无意的不匹配的事情。

当头文件中定义了内联函数,且编译器编译为了内联函数,则源文件中包含该头文件后,对应的函数代码将会在该源文件中自动被复制。

可能有在思考的同学又会有疑问了(如果你没想到这个问题,我也不怪你)
函数是否真的内联是由编译器决定的,若软件开发者在头文件中定义了内联函数,而编译器却又未执行内联处理,那在多个源文件包含时不就又会报重定义的错误吗?

答:如果是单纯的只定义inline关键字,确实是有可能会出现这种情况的。所以一般在定义内联函数时,除了inline之外,还会在前面加上static关键字,成为LOCAL_INLINE,有了static关键字的存在,即使编译器没有将定义的inline函数进行inline处理,也不会出现重定义的错误。

总结

如果函数真的成了inline函数,那么在调试过程中,将无法通过打断点的方式调试该函数执行过程。如果想要方便调试inline函数,一般可以通过禁用编译器优化,不执行内联。例如,在Greenhills中,可以通过配置-Omaxdebug来实现。

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

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

相关文章

从零开始搭建游戏服务器 第三节 Protobuf的引入并使用

目录 上一节问题答案公布本节内容Protobuf介绍正文在build.gradle引入protobuf编写proto并生成使用生成的proto来进行数据传输 总结 上一节问题答案公布 上一节我们创建了ConnectActor,并且使用ConnectActorManager和connectId将其管理起来。 并且我们在收到客户端…

【Twinmotion】Twinmotion导入UE5

步骤 1. 在虚幻商城中安装“Datasmith Twinmotion导入器插件” 安装“面向虚幻引擎的Twinmotion内容” 2. 打开虚幻引擎,在插件中搜索“twinmotion”,勾选如下两个插件,然后重启虚幻引擎 3. 打开Twinmotion,随便添加一个物体 导出…

腾讯云2核2G免费服务器申请流程,2024免费服务器入口

腾讯云免费服务器申请入口 https://curl.qcloud.com/FJhqoVDP 免费服务器可选轻量应用服务器和云服务器CVM,轻量配置可选2核2G3M、2核8G7M和4核8G12M,CVM云服务器可选2核2G3M和2核4G3M配置,腾讯云服务器网txyfwq.com分享2024年最新腾讯云免费…

4.1_5 文件存储空间管理

文章目录 4.1_5 文件存储空间管理(一)存储空间的划分与初始化(二)存储空间管理——空闲表法(三)存储空间管理——空闲链表法(1)空闲盘块链(2)空闲盘区链 &…

VScode----debug调试python代码添加上额外命令(args)

这里写目录标题 问题描述问题解决 更多内容可以点击这里查看个人博客:个人博客 问题描述 在服务器上运行python代码时,总会添加上额外的参数一般是用jyputer或者终端直接加上命令,现在我在vscode调试远程代码的时候想要加上这些命令. 问…

DFL《384底丹 430万》 wf/df-udt/448/96/96/32预训练模型

384底丹430万迭代:点击下载 训练素材19万张来自于以下数据集: 【更新】DST全角度训练图集V3.1 WF512【2.6W张 6GB 】【人脸混合_WF】FFHQ女性人脸数据,预训练炼丹专用【金鱼基础模型库】用于补全SRC极限角度香港中文大学CelebA预训练集-WF5…

HarmonyOS NEXT应用开发—状态栏显隐变化

介绍 本示例介绍使用Scroll组件的滚动事件 onScroll 实现状态栏显隐变化。该场景多用于各种软件的首页、我的等页面中。 效果预览图 使用说明 加载完成后显示状态栏显隐变化页面,上下拖动屏幕,顶端状态栏出现显隐变化。 实现思路 在置顶位置使用sta…

Vue-router3.0版本跳转报错

1.路由创建之后发现控制台push路由跳转报错了 2.解决方法: //在router文件中添加 const originalPush VueRouter.prototype.push VueRouter.prototype.push function push(location) {return originalPush.call(this, location).catch(err > err) }3.解决了

webpack5零基础入门-10babel的使用

Babel JavaScript 编译器。 主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中 1.安装相关包 npm install -D babel-loader babel/core babel/preset-env 2.进行相关配置 2.1第一种写法是在webp…

Day67:WEB攻防-Java安全JNDIRMILDAP五大不安全组件RCE执行不出网

知识点: 1、Java安全-RCE执行-5大类函数调用 2、Java安全-JNDI注入-RMI&LDAP&高版本 3、Java安全-不安全组件-Shiro&FastJson&JackJson&XStream&Log4j Java安全-RCE执行-5大类函数调用 Java中代码执行的类: GroovyRuntimeExecPr…

git如何回退版本reset和revert命令的区别

文章目录 git回退版本的方法使用reset回退使用revert回退 总结 git回退版本的方法 Git回退到某个版本有两种方法&#xff1a;reset和revert。 使用reset回退 git reset --hard <版本号>该命令将HEAD指针移动到指定的版本&#xff0c;并重置工作目录和暂存区的内容。这…

微信小程序Skyline模式自定义tab组件胶囊与原生胶囊平齐,安卓和ios均自适应

进入下面小程序可以体验效果&#xff1a; 至于原理的话&#xff0c;解释起来毕竟麻烦&#xff0c;各位可以看源码自己分析。其实很简单&#xff0c;就算计算布局。很多网上公布的布局&#xff0c;都不能正常自适应。在下这个是完美可以的 1、WXML <view class"weui…

【遍历方法】浅析Java中字符串、数组、集合的遍历

目录 前言 字符串篇 1.1 使用 for 循环和 charAt 方法 1.2 使用增强 for 循环&#xff08;forEach 循环&#xff09; 1.3 使用 Java 8 的 Stream API 最终效果 数组篇 2.1 使用普通 for 循环 2.2 使用增强型 for 循环( forEach 循环) 2.3 使用 Arrays.asList 和 forE…

Python之Web开发中级教程----配置数据库

Python之Web开发中级教程----配置数据库 在settings.py中保存了数据库的连接配置信息&#xff0c;Django默认初始配置使用sqlite数据库。 DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: os.path.join(BASE_DIR, db.sqlite3), } } 如果需要用MySQL数据…

LeetCode 0310.最小高度树:拓扑排序秒了

【LetMeFly】310.最小高度树&#xff1a;拓扑排序秒了 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-height-trees/ 树是一个无向图&#xff0c;其中任何两个顶点只通过一条路径连接。 换句话说&#xff0c;一个任何没有简单环路的连通图都是一棵树。 给你…

nginx做静态代理方式

改配置文件 server {listen 8899;server_name localhost;location / {root html;index index.html index.htm;} } 生成页面代码 例子 GetMapping("createIndex")public Result createIndex() {//获取后台存储数据Result result productFeignClient.getB…

python之万花尺

1、使用模块 import sys, random, argparse import numpy as np import math import turtle import random from PIL import Image from datetime import datetime from math import gcd 依次使用pip下载即可 2、代码 import sys, random, argparse import numpy as np imp…

Linux环境开发工具之yum

前言 前面我们已经对基本的指令和权限进行了介绍&#xff0c;本期开始我们将介绍常用的开发工具。例如&#xff1a;软件包管理器yum。 本期内容介绍 Linux上安装软件的方式 什么是yum yum的相关操作 yum的本地配置和yum源 一、Linux上安装软件的方式 在介绍Linux上如何安装一…

Docker 安装 Skywalking以及UI界面

关于Skywalking 在现代分布式系统架构中&#xff0c;应用性能监控&#xff08;Application Performance Monitoring, APM&#xff09;扮演着至关重要的角色。本文将聚焦于一款备受瞩目的开源APM工具——Apache Skywalking&#xff0c;通过对其功能特性和工作原理的详细介绍&am…

打破数据孤岛,TDengine 与 Tapdata 实现兼容性互认证

当前&#xff0c;传统行业正面临着数字化升级的紧迫需求&#xff0c;但海量时序数据的处理以及数据孤岛问题却日益突出。越来越多的传统企业选择引入时序数据库&#xff08;Time Series Database&#xff0c;TSDB&#xff09;升级数据架构&#xff0c;同时&#xff0c;为了克服…