头皮发麻,这函数参数太多了~

2023-12-04 10:20

本文主要是介绍头皮发麻,这函数参数太多了~,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

5352b207468bd7ff89e62966dc6022b8.gif

正文


大家好,我是bug菌~

过完正月十五就真的开启新的一年了,年初工作上挺忙碌的,各种开会和各种项目计划,忙着树立各种flag。

或许早已习惯了,计划基本都赶不上变化,"梦想很丰满,现实很骨感吧",这就是大部分公司所谓的年初工作仪式感吧。

本文主要是跟谈谈函数参数太多这个问题,其实应该早一点跟大家聊聊的,毕竟牵涉到软件代码的设计。主要还是因为平时很多话题写文章的时候又想不到,遇到了又不一定会想到要写到文章中去,所以迟迟没有涉及到。

那么今天就针对函数参数数量问题做一个分析和编码建议:

1

函数参数的传递

既然本文谈到函数参数的个数问题,首先就需要了解函数参数到底是如何传递的,并且其影响着什么?

函数的调用过程主要是依赖函数调用栈,对于栈的原理很简单-先进后出,而对于函数调用栈主要是在该栈中分配内存以供函数临时使用-(即压栈),而当函数返回便是一个栈回溯的过程-(即出栈)。

所以函数的参数跟局部变量一样都分配到栈上,当然为了提高函数调用速度,相关变量会直接通过寄存器来传递,原理上也是类似的。

在嵌入式开发中经常会有C语言与汇编语言相互调用的编码形式,这样就需要遵循一定的调用原则。对于使用甚广的ARM内核都遵循ARM过程调用标准APCS(ARM Procedure Call Standard)。

该标准中规定了各种寄存器的使用限制、栈的使用规则、以及函数调用过程中的参数传递返回等,大家编程的时候可以参考相关ARM手册进行了解。

对于函数调用优先会采用R0~R3传递参数,且不需要恢复,那么如果超过4个参数则只能通过栈来传递,相比寄存器传递需要耗费更多的时间压栈和出栈。

所以这也是为什么有些人经常说函数参数最好不要超过4个或者过多的原因。

2

参数太多引起的问题

前面bug菌在谈及参数太多会导致函数调用更加的耗时,因为增加了参数入栈和出栈的时间,特别是一些循环语句中调用参数较多的子函数。

而对性能上的影响,对于大部分朋友所做的项目可能并不是很在意,快点慢点也无所谓,一般用户也体会不到,毕竟现在的芯片性能都还不错,可以为低效的代码买单。

但是参数太多对于编码风格却是大煞风景,更值得注意的是很容易让编码人员犯错。

bug菌之前就遇到一种情况:

1void Function(int param1,int param2,int param3,int param4,int param5\2              int param6,int param7,int param8,int param9,int param10)3{45    ......6}78int main(void)9{
10    ......
11
12    Function(Val1,Val2,Val3,Val4,Val5,Val6,Val7,Val8,Val9,Val10);
13    ......
14}

如以上代码,由于参数太多,在传递参数的过程中,传递顺序不小心错乱了,编译仍然可以正常通过,但程序就引入了bug导致出错。

3

如何处理函数参数

那参数多少才算多?

其实并没有严格的界定,因为最终大量的参数定义都会在栈上分配,只要不把栈撑爆了,都是允许的。

对于C语言的参数传递,主要是两种方式,一种就是传值和传地址。

如果一个函数内部不依赖于静态全局区参数或者函数外部存储区,数据均来源于函数参数,那么随着需求不断的变化,函数功能更加的丰富多变,参数也将随着变大。

经常听有些朋友说直接把参数封装成结构体来进行传递,这样的处理虽然能够在一定程度上减少函数参数顺序错乱带来的风险,但与各参数分别传递并没有太大的改善。

就类似于如下代码:

1void process(void)23{4    sPara.m1 = 1;5    sPara.m2 = 2;6    sPara.m3 = 3;7    sPara.m4 = 4;8    .....9
10    process(sPara);    
11}

同时我个人还是不建议简单地用来减少参数数量进行数据打包,结构体应当尽量表现业务上的关联性,当然如果你一定在数据之间强加一种关系,那我也没办法。

同时一个函数一般只实现一种功能,不要把太多的功能放到一个函数中,一方面把函数写得特别长,另一方面就是会使得参数特别多,因为这些参数都和特定的功能相关。

似乎单独值传递并不能直接改善参数太多带来的弊端。

那么就必须借助函数以外的存储区来作为相关参数的存储位置,参数仅仅只是索引,更多的参数和信息还需要根据传递的地址或者是索引来获得,这样就降低了调用函数参数太多所带来的负担。

以前也跟大家介绍过一些C语言面向对象程序的设计,所有的数据和方法都会封装到一个结构体对象中,这对于相关方法函数的调用只需要传递相应的对象地址给形参指针,一个指针多大?应该不用我多说了吧。

当然也没有十全十美的事情,子函数引用函数以外存储区可能相对没有那么独立,因为外部存储区可能会发生参数变化,从而导致子程序运行结果发生变化,这一点是值得注意的,特别是对于多线程编程。

最后

      好了,今天就跟大家分享这么多了,都是bug菌平时总结的C语言编程技巧,好好品味一下,如果你觉得有所收获,一定记得点个~

最后一个bug,bug菌唯一创作平台~

a79c40e283bd9e6491a5b7533189a745.png

推荐专辑  点击蓝色字体即可跳转

☞  MCU进阶专辑 86affc6790e9edae215f024bb9604b18.gif

☞  嵌入式C语言进阶专辑 861d35db462f72028a26ef75d41ded41.gif

☞  “bug说”专辑 73526e35e454ab9c105f16a1c55b89e7.gif

☞ 专辑|Linux应用程序编程大全

☞ 专辑|学点网络知识

☞ 专辑|手撕C语言

☞ 专辑|手撕C++语言

☞ 专辑|经验分享

☞ 专辑|电能控制技术

☞ 专辑 | 从单片机到Linux

6d71d271fb3bf4428540f95b409e9d23.gif

这篇关于头皮发麻,这函数参数太多了~的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/453110

相关文章

【机器人工具箱Robotics Toolbox开发笔记(二十)】机器人工具箱SerialLink I类函数参数说明

机器人工具箱中的SerialLink表示串联机器人型机器人的具体类。该类使用D-H参数描述,每个关节一组。SerialLink I类包含的参数如表1所示。 表1 SerialLink I类参数 参  数 意    义 参  数 意    义 plot 显示机器人的图形表示 jacobn 工具坐标系中的雅可比矩阵 plot3D 显示机器人3D图形模型 Jacob_dot

HBASE列族不能太多的真相

点击上方蓝色字体,选择“设为星标” 回复”资源“获取更多资源 大数据技术与架构 点击右侧关注,大数据开发领域最强公众号! 暴走大数据 点击右侧关注,暴走大数据! ‍ ‍HRegionServer内部管理了一系列HRegion对象,每个HRegion对 应了table中的一个region,HRegion中由多 个HStore组成。每个HStore对应了Table中的一个column fa

C++---函数参数的内存开辟

参数类型: 形参:函数名后括号中的变量; 实参:真实传给函数的参数,可以是:常量、变量、表达式、函数等。无论实参是何种类型,调用时,它们必须有确定的值,以便把这些值传送给形参。 调用前: 形参:由于函数没有调用,编译系统没有给函数的形参分配实际内存空间,因此没有实际的参数值。 调用时: 形参:实际调用时,系统会给函数的各形参分配存储空间,同时将实参的值依次传递给各形参,调用结束后,系统

prometheus grafana sql 常用函数参数

1. sum(..) by(instance) (increase()) 以instance分组然后相加        2. sum(..) without(instance) 去除instance,以剩下的标签分组然后相加   3. increase(..[1m])  一分钟内的值    4. rate(..[1m])  一分钟内的值除以60秒,如果是2m, 就除以120

C++入门基础知识47——【关于C++函数】之函数参数及参数默认值

成长路上不孤单😊【14后,C++爱好者,持续分享所学,如有需要欢迎收藏转发😊😊😊😊😊😊😊!!!!!!今日分享关于C++函数之函数参数及参数默认值的相关内容! (接上篇……) 四、函数参数 如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。 形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。 当调用函数时,有两种向函数传递

Python 函数参数类型检查

Python 函数参数类型检查 tags: Python, lint, type-checking, mypycreate: 2024.09.01 12:40author: ChrisZZ imzhuo@foxmail.com 1. 问题描述 在 test.py 中编写了代码: 定义函数: def hello(capitalize: bool=False):if capitalize:p

类对象作为函数参数

对象也可以作为函数的参数传递给函数,其转递方法与传递其他类型的数据一样,可采用值传递和地址传递两种方法。 值传递时是把对象的拷贝而不是本身传递给函数,函数中对参数对象的任何修改都不会影响调用该函数的对象本身; 而地址传递时,调用该函数的对象与参数对象共用同一个地址,所以,函数对参数对象的任何修改都会影响调用该函数的对象本身。   上面是拷贝的别人的语句:   但是自己在编程实现的时候如果把类对象

python中的函数参数定义和可变参数详解

刚学用Python的时候,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和**让人有点费解。其实只要把函数参数定义搞清楚了,就不难理解了。 先说说函数定义,我们都知道,下面的代码定义了一个函数funcA def funcA():   pass      显然,函数funcA没有参数(同时啥也不干:D)。 下面这个函数f

Python编程学习第一篇——Python零基础快速入门(六)(6)函数参数

本节接着讲函数,主要说说函数的参数,在Python中,函数的参数可以分为位置参数、默认参数、可变参数和关键字参数。下面将详细介绍各种类型的参数和参数传递方式。 1. 位置参数: 位置参数是指按照定义函数时参数的顺序传递的参数。当调用函数时,实参的顺序必须与形参一一对应。 示例代码: def add(x, y):return x + yresult = add(3, 5)print(resu

Modern C++——函数参数类型的分类和使用

大纲 基本定义值类型左值引用非常量左值引用常量左值引用 右值引用总结 在C++中,函数参数主要有两种方式:值类型和引用类型。其中引用类型又分为:左值引用和C++11引入的右值引用。下面我们分别对其进行介绍。 基本定义 要弄清楚这些概念,我们先要知道什么是左值,什么是右值。 左值是指在内存中有确定存储地址的对象,可以在表达式中出现在赋值操作符的左侧。右值是指在表达式中没有持久存