C语言: 函数调用的开销

函数调用的开销 阅读详情

转载请注明来源 http://blog.youkuaiyun.com/imred/article/details/48865359
初学C语言的时候,我们有时会听说函数调用会有一定的开销,在进行了进一步学习之后,我们来看看原来听说的开销指的什么。
下面是两个非常简单的样例,就不作解释了:
函数调用版本C程序:

#include <stdio.h>

int sum(int a, int b)
{
return a + b;
}

int main()
{
int a = 1;
int b = 1;
int c;
c = sum(a, b);
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

使用gcc汇编后:

    .file   "function.c"
    .text
    .globl  _sum
    .def    _sum;   .scl    2;  .type   32; .endef
_sum:
    pushl   %ebp
    movl    %esp, %ebp
    movl    12(%ebp), %eax
    movl    8(%ebp), %edx
    addl    %edx, %eax
    popl    %ebp
    ret
    .def    ___main;    .scl    2;  .type   32; .endef
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    call    ___main
    movl    $1, 28(%esp)
    movl    $1, 24(%esp)
    movl    24(%esp), %eax
    movl    %eax, 4(%esp)
    movl    28(%esp), %eax
    movl    %eax, (%esp)
    call    _sum
    movl    %eax, 20(%esp)
    movl    $0, %eax
    leave
    ret
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

无函数调用版本c程序:

#include <stdio.h>

int main()
{
int a = 1;
int b = 1;
int c;
c = a + b;
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

使用gcc汇编后:

    .file   "no_function.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $1, 12(%esp)
    movl    $1, 8(%esp)
    movl    8(%esp), %eax
    movl    12(%esp), %edx
    addl    %edx, %eax
    movl    %eax, 4(%esp)
    movl    $0, %eax
    leave
    ret
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

除了公共部分和指导信息之外,第一个汇编程序比第二个汇编程序多了以下内容:

1

    movl    24(%esp), %eax
    movl    %eax, 4(%esp)
    movl    28(%esp), %eax
    movl    %eax, (%esp)
 
  • 1
  • 2
  • 3
  • 4

2

    call    _sum
 
  • 1

3

    pushl   %ebp
    movl    %esp, %ebp
 
  • 1
  • 2

4

    popl    %ebp
    ret
 
  • 1
  • 2

额外的开销就体现在这4段代码上了,我来一一解释一下它们的作用:

1

参数入栈代码,将函数参数入栈,这是现在函数调用的标准方式。参数越多,开销越大

2

将控制权转移至函数中

3

建立新的栈帧,也就是当前函数使用的“一片”栈空间,使用ebp的值来标识新的栈帧,因此要将原栈帧首地址保存下来,方便回到原来的即调用者的栈帧

4

恢复原栈帧,然后将控制权转移至调用者
从汇编的角度来看,这额外的开销就是指的这不足十行的指令了,会对性能有多大影响呢?大概有那么一丁点。当然,对于不同的函数,以及不同的调用频率,这个影响也不尽相同。当然,这个程序是一个极端,它函数的功能代码也只有3行,这样的情况完全可以不用函数或者使用内联函数。所以是使用函数还是不使用函数呢?依我来看,为了程序的可读性,我们还是牺牲那么一丁点的性能吧。
转载请注明来源 http://blog.youkuaiyun.com/imred/article/details/48865359

告别函数调用开销——C语言宏函数深度解析 【摘要】C语言宏函数通过预编译阶段的文本替换机制,可以有效规避函数调用的时间开销。本文解析了宏函数的优势与风险:直接替换避免了参数入栈、跳转执行等函数调用流程,显著提升性能;但纯文本替换特性易受运算符优先级影响。通过案例展示了不加括号的宏函数会导致逻辑错误,提出"整体和参数都加括号"的黄金法则。宏函数适用于简单、频繁调用且对性能要求苛刻的场景,如嵌入式系统和高性能计算。正确使用宏函数能以代码空间换取执行时间,但需警惕运算符优先级陷阱。 阅读详情

相关推荐

C/C++ 函数调用以及Linux中系统调用 开销介绍:介绍C/C函数调用以及Linux中系统调用的开销情况

C/C++ 函数调用开销

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1774

【函数调用需要哪些开销,内联函数又做了什么?】

这篇文章主要为大家讲解了函数调用所需要的开销以及内联函数的功能,内联函数可以为函数的调用节省掉许多的开销,这篇文章涉及到了很多关于函数调用的知识,这其中又穿插了很多关于操作系统和计算机组成原理的相关知识,不管是考研还是就业这部分的知识都是非常有用的,希望能够帮助到大家!

weixin_59658448的博客 2032

C++性能优化:减少函数调用开销

C++面试题

夏天的狂风的专栏 635

C++ 函数调用时间开销

C++函数调用时间开销1.前言2.函数调用约定3.函数类型3.1.普通函数3.2.模板函数3.3 内联函数3.4 宏函数3.4 虚函数4.函数调用开销测试附页 1.前言          调用函数的开销大致可分两个部分:传递参数的开销和保存当前程序上下文信息所花费的开销。对于传递参数的开销而言,传递的参数越多...

ayww的博客 6931

数据讲述中国故事!和鲸助力中国综合社会调查(CGSS)数据分析与可视化大赛圆满收官

用数据研究中国问题、总结中国道路、讲述中国故事。和鲸作为协办单位全程支持本次大赛,为中国人民大学中国调查与数据中心实施全套赛事系统,同时提供完备而周全的赛事运营服务。

ModelWhale的博客 1410

C语言 time函数 开销,C语言: 函数调用的开销

初学C语言的时候,我们有时会听说函数调用会有一定的开销,在进行了进一步学习之后,我们来看看原来听说的开销指的什么。下面是两个非常简单的样例,就不作解释了:函数调用版本C程序:#include int sum(int a, int b){return a + b;}int main(){int a = 1;int b = 1;int c;c = sum(a, b);return 0;}使用gcc汇编...

weixin_39914049的博客 317

卡尔曼滤波调参避坑指南:Q/R参数怎么设?实测5种传感器场景

本文针对卡尔曼滤波在工程实践中Q/R参数设置的难题,提供了一套实用的调参避坑指南。通过分析过程噪声方差Q与测量噪声方差R的物理意义与博弈关系,并结合温度传感器、陀螺仪、超声波测距等五种典型传感器场景的实测效果对比,总结出从噪声估算、离线仿真到收敛测试的系统性调参方法论,帮助工程师快速实现稳定有效的滤波效果。

weixin_29174141的博客 799

【性能优化关键】:C语言与WASM通信中函数调用开销降低80%的秘诀

掌握C语言与WASM通信的高效函数调用优化方法,显著降低80%性能开销。适用于Web高性能计算、游戏引擎等场景,通过减少胶水代码与内存复制提升交互效率。深入解析接口设计与编译策略,值得收藏。

LiteProceed的博客 590

【土壤普查实战】Python+ArcGIS随机森林模型一键生成土壤类型栅格图

本文详细介绍了如何利用Python和ArcGIS结合随机森林模型实现土壤类型栅格图的自动化生成,大幅提升土壤普查效率。通过环境准备、数据预处理、模型构建与调优等关键步骤,帮助用户掌握从样本点生成到最终栅格图输出的完整流程,适用于大面积区域或样本点较多的土壤分类任务。

weixin_29229989的博客 217

从M350 RTK到E-Port:解锁大疆无人机多负载协同与PSDK V3开发新范式

本文深入解析了大疆M350 RTK无人机搭载的E-Port智能接口与全新的PSDK V3开发套件,如何共同实现多负载协同作业的范式转变。E-Port集成了供电与高速数据总线,而PSDK V3通过统一的设备模型与服务机制,大幅降低了第三方负载的开发门槛与集成复杂度,使构建如智能巡检等复杂空中作业系统变得更加高效和标准化。

3c4x5z6v7b的博客 166

从程序执行效率来说,C语言采取的措施和原因

1.使用指针:对于指针的理解简单点可以认为类似于汇编中的寻址方式,正是指针的存在使C语言威力无穷。有些程序用其他语言也可以实现,但C能够更有效地实现;有些程序无法用其它语言实现,如直接访问硬件,但C却可以。正因为指针可以拥有类似于汇编的寻址方式,所以可以使程序更高效。 2.使用宏函数:函数和宏函数的区别就在于,宏函数占用了大量的空间,而函数占用了时间。函数调用是要使用系统的栈来保存数据的,如果编译...

R的博客 2229

MPU6050 vs BMX055 vs ICM20602:如何为你的项目选择最佳陀螺仪(附实测数据对比)

本文深度对比了MPU6050、BMX055和ICM20602三款主流六轴IMU传感器的核心性能。通过实测数据,分析了它们在精度、噪声、温漂、接口速度及资源占用上的差异,并提供了从项目需求出发的选型指南,帮助开发者根据预算、精度要求和处理器性能选择最合适的陀螺仪与加速度计组合。

h0i1j2k3l的博客 969

系统调用和函数调用的区别

系统调用 操作系统服务的编程接口 通常由高级语言编写(C或C++) 程序访问通常通过高层次 的API接口(C标准库的库函数)而不是直接进行系统调用 每个系统调用对应一个系统调用编号 系统调用与函数调用的区别 系统调用 使用INT和IRET指令,内核和应用程序使用的是不同的堆栈,因此存在堆栈的切换,从用户态切换到内核态,从而可以使用特权指令操控设备, 函数调用 使用CALL和RET...

十分残念的博客 1万+

“三进制”bonsai27b+NInfer=6g显存闪电侠(token真的自由了!)

本文将1.58-bit三元大模型Bonsai27B成功移植至NInfer推理引擎,并在RTX 4080 SUPER上实现100+ token/s的极速推理。通过自研补丁扩展NInfer支持Ada架构与三元量化格式,解决激活布局、行置换等关键bug,实测PPL 6.445,单流吞吐达96.7–130.8 t/s,20题基准得分16/20。附完整复现包(含文档、工具、源码补丁),零权重分发,助力垃圾显卡跑通27B级模型。

shensanshu的博客 1万+

3D视觉-激光三角测量法的概述和原理

激光三角法位移测量的原理是,用一束激光以某一角度聚焦在被测物体表面,然后从另一角度对物体表面上的激光光斑进行成像,物体表面激光照射点的位置高度不同,所接受散射或反射光线的角度也不同,用。激光三角测量法是一种通过图像采集系统采集被测物表面漫反射的激光轮廓,进而基于设备已知的相对位置通过算法处理,获得被测物表面的三维轮廓数据,进而还原目标物体三维空间信息的方法。采用激光三角原理和回波分析原理进行非接触位置、位移测量的精密传感器, 广泛应用于位置、位移 、厚度、半径、形状、振动、距离等几何量的工业测量。

qq_20660115的博客 3919

【C++】优化函数对象:提升性能和内存效率

函数对象 =》c语言里面的函数指针、对象构造优化、对象使用过程中背后调用的方法、函数调用过程中对象背后调用方法:、优化原则、move,forward

小洁洁 1204

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

48.【C语言】结构体补充

原因:结构体与一般的数组不一样,当结构体中的数组比较大时(int arr[9999] )在传值时会复制一份一样的int arr[9999],占用大量空间,降低效率;s为arr和n赋值,arr的前5个元素分别赋值为1,2,3,4,5,其余默认为0,n赋值为100。传参时function(int a)中int是变量类型,a是变量名。定义结构体S中的两个结构体成员,分别为arr整型数组和整型变量n。中int是变量类型,a是变量名,0是变量值。struct S s:S代表结构布局,s代表结构变量。

zhangcoder的博客 记录学习轨迹~ 1065

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

为什么你的TinyML模型跑不快?C语言底层优化的4个隐藏陷阱

提升TinyML推理速度的关键在于C语言底层优化,本文揭示4个常见性能陷阱及规避方法,涵盖内存访问、数据类型与循环展开等核心技巧,适用于嵌入式与边缘计算场景,助你显著加速模型运行,值得收藏。

LiteTrans的博客 1027

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

从编译器视角看单片机开发:为什么C语言仍是微控制器世界的‘母语’?

本文从编译器视角分析单片机开发中C语言的主导地位。C语言凭借其简洁语法、直接硬件映射能力和高效编译优化,在资源受限的微控制器环境中展现出显著优势,相比C++能生成更小代码体积和更高执行效率,仍是嵌入式系统开发的‘母语’。

kiwi8的博客 162

终极C语言归并排序指南:从递归到非递归实现的完整教程

GitHub 加速计划 / c / C 项目是一个专注于用 C 语言实现数学、机器学习、计算机科学等领域各种算法的教育资源集合。归并排序作为经典的分治算法,在该项目的 [sorting/merge_sort.c](https://link.gitcode.com/i/419014ab7a99265256c306a1eec196cf) 文件中得到了清晰实现,本文将带您深入理解其递归与非递归实现技巧。

gitblog_00412的博客 289

【轻松学C:编程小白的大冒险】--- 18 内联函数的概念与优势

在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。

秋知叶i 1051

终极指南:Go语言CGO性能深度剖析与跨语言调用优化策略

《Go语言高级编程》开源图书中的CGO特性实现了Go语言对C语言和C++语言的支持,使得Go语言可以无缝继承C/C++世界数十年来积累的巨大软件资产。然而,CGO带来便利的同时也伴随着性能挑战,本文将深入剖析跨语言调用的成本,并提供实用的优化策略。 ## CGO跨语言调用的性能瓶颈 CGO作为连接Go与C的桥梁,其性能损耗主要来自三个方面:**内存模型差异**、**函数调用开销**和**数据转

gitblog_00762的博客 973

C语言中的带参宏和带参函数的区别

C语言中的static关键字     (1) 修饰局部变量,限定变量的生命周期。变量的存储类别由栈区变为静态数据区。 int main() { int x=9; //普通局部变量,存储在栈区 static int x=9; //静态局部变量,存储在静态数据区 return 0; }     (2)...

hw_xqzp_success的博客 2894

C语言为何无法替代?从Linux内核到航天器,谁都绕不开它

C语言还在写操作系统,程序员早就不爱它了,可谁也绕不开它。最近翻Linux内核源码,看到`mm/memory.c`里全是带`volatile`的指针,一行行读下来

dai_jiaqi的博客 315
上一篇: C语言中volatile关键字的作用
下一篇: Cortex-M的M0,M+,M3,M4,M7几种内核的简单区别
csshuke
博客等级 码龄16年 1517粉丝 8原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值