0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

对嵌入式C语言优化技巧详细教学

GReq_mcu168 来源:CSDN技术社区 作者:求佛_ce123 2021-04-07 11:30 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

嵌入式系统是指完成一种或几种特定功能的计算机系统,具有自动化程度高,响应速度快等优点,目前已广泛应用于消费电子工业控制等领域。嵌入式系统受其使用的硬件以及运行环境的限制,非常注重代码的时间和空间效率,因此选择一种合适的开发语言十分重要。

目前,在嵌入式系统开发中可使用的语言很多,其中 C语言应用得最广泛。虽然用 C 语言编程具有许多优点,但基于嵌入式系统的C语言和标准 C语言又有很大区别。接下来小编结合嵌入式系统的特点和高手们的一些积累,给大家整理出在程序设计中代码优化的一些小技巧。

1、嵌入式C语言的特点

作为一种结构化程序设计语言,C 语言兼顾多种高级语言的特点,具有很强的功能性和可移植性。但在嵌入式系统开发中,出于对低价产品的需求,系统的计算能力和存储容量都非常有限,因此如何利用好这些资源就显得十分重要。开发人员应注意嵌入式 C语言和标准 C 语言的区别,减少生成代码长度,提高程序执行效率,在程序设计中对代码进行优化。

2、C代码在程序中的优化

现在的 C 编译器会自动对代码进行优化,但这些优化是对执行速度和代码长度的平衡。如果要获得更小且执行效率更高的代码,需要程序员手工对代码进行优化。

3、变量类型的定义

不同的数据类型所生成的机器代码长度相差很多,变量类型选取的范围越小运行速度越快,占用的内存越少。能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变量就不要用长整型(long int),能不使用浮点型(float)变量就不要使用浮点型变量。相同类型的数据类型,有无符号对机器代码长度也有影响。因此我们应按照实际需要合理的选用数据类型。当然,在定义变量后不要超过变量的作用范围,如果超过变量的范围赋值,C编译器并不报错,但程序运行结果却错了,而且这样的错误很难发现。

4、算法优化

算法优化指对程序时空复杂度的优化:在 PC 机上进行程序设计时一般不必过多关注程序代码的长短,只需考虑功能的实现,但嵌入式系统就必须考虑系统的硬件资源,在程序设计时,应尽量采用生成代码短的算法,在不影响程序功能实现的情况下优化算法。

5、适当的使用宏

在C程序中使用宏代码可以提高程序的执行效率。宏代码本身不是函数,但使用起来像函数。函数调用要使用系统的栈来保存数据,同时 CPU 在函数调用时需要保存和恢复当前的现场,进行进栈和出栈操作,所以函数调用也需要 CPU时间。而宏定义就没有这个问题:宏定义仅仅作为预先写好的代码嵌入到当前程序中,不产生函数调用,所占用的仅仅是一些空间,省去了参数压栈,生成汇编语言的 call 调用,返回参数,执行 return等过程,从而提高了程序的执行速度。虽然宏破坏了程序的可读性,使排错更加麻烦,但对于嵌入式系统,为了达到要求的性能,嵌入代码常常是必须的做法。

此外,我们还要避免不必要的函数调用,请看下面的代码:

[plain] view plain copy print?void str_print( char *str ){int i;for ( i = 0; i 《 strlen ( str ); i++ ){ printf(“%c”,str[ i ] ); } }void str_print1 ( char *str ){int len;len = strlen ( str );for ( i = 0; i 《 len; i++ ){printf(“%c”,str[ i ] );}}

请注意,这两个函数的功能相似。然而,第一个函数调用strlen函数多次,而第二个函数只调用函数strlen一次。因此第二个函数性能明显比第一个好。

6、内嵌汇编

程序中对时间要求苛刻的部分可以用内嵌汇编来重写,以带来速度上的显着提高。但是,开发和测试汇编代码是一件辛苦的工作,它将花费更长的时间,因而要慎重选择要用汇编的部分。在程序中,存在一个80-20原则,即20%的程序消耗了80%的运行时间,因而我们要改进效率,最主要是考虑改进那20%的代码。

7、提高循环语言的效率

在 C 语言中循环语句使用频繁,提高循环体效率的基本办法就是降低循环体的复杂性:

(1) 在多重循环中,应将最长的循环放在最内层,最短的循环放在最外层。这样可以减少 CPU跨切循环的次数。如例 1-1 的效率比 1-2 的效率要低:

[plain] view plain copy print?for (j = 0; j 《 30; j++){for (i = 0; i 《 10; i++){……}} // 例子 1-1 for (i = 0; i 《 10; i++){for (j = 0; j 《 30; j++) {……}} // 例子 2-2 程序部简洁但效率高

8、提高 switch 语句的效率

switch 语句是 C 语言中常用的选择语句, 在编译时会产生if- else- if 嵌套代码,并按照顺序进行比较,发现匹配时,就跳转到满足条件的语句执行。

当 switch 语句中的 case 标号很多时,为了减少比较的次数,可以把发生频率相对高的条件放到第一位或者把整个 switch 语句转化嵌套 switch 语句。把发生频率高的 case 标号放在最外层的 switch 语句中,发生相对频率相对低的 case 标号放在另外的 switch 语句中。如例 3 中,把发生率高的case 标号放在外层的 switch 语句中,把发生频率低的放在缺省的(default)内层 switch 语句中。

[plain] view plain copy print? switch (表达式) { case 值1:语句1: break;case 值2:语句2:break; ……/*把发生频率低的放在内层的switch语句中*/default:switch (表达式) {case 值n:语句n: break;case 值m:语句m: break;……}}例子3 使用嵌套switch语句提高程序执行效率。

9、避免使用标准库

使用 C语言标准库可以加快开发进度,但由于标准库需要设法处理用户所有可能遇到的情况,所以很多标准库代码很大。比如标准库中的 sprintf函数非常大。这个庞大的代码中有很大一部分用于处理浮点数,如果程序中不需要格式化浮点数值( 如%f),程序设计人员就可以根据实际情况用少量的代码实现这个功能。

10、采用数学方法优化程序

数学是计算机之母,没有数学的依据和基础,就没有计算机的发展,所以在编写程序的时候,采用一些数学方法会对程序的执行效率有数量级的提高。有时候这个问题常常被大家忽略, 对于没有经验的程序员来说更是如此。例如:求 1~100 的和:

sum = 100*(100+1)/2;数学公式: (a1 + an)*n/2

使用C语言的位操作可以减少除法和取模的运算。在计算机程序中数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的运算和操作。因而,灵活的位操作可以有效地提高程序运行的效率。比如用用位操作区代替除法:比如:128 / 8 -》》 128 》》 3;

优化算法和数据结构对提高代码的效率有很大的帮助。当然有时候时间效率和空间效率是对立的,此时应分析哪个更重要, 做出适当的折中。另外,在进行优化的时候不要片面的追求紧凑的代码,因为紧凑的代码并不能产生高效率的机器码。

11、存储器分配

由于成本限制,嵌入式系统存储器容量有限。程序中所有的变量,包含的库函数以及堆栈等都使用有限的内存:全局变量在整个程序范围内都有效。程序执行完后才会释放;静态变量的作用范围也是整个程序,只有局部变量中的动态变量在函数执行完后会释放。因此, 在程序中应尽量使用局部变量,提高内存使用效率。程序中堆的大小受限于所有全局数据和栈空间都分配后的剩余量,如果堆太小,程序不能够在需要的时候分配内存。因此在使用 malloc 函数申请内存之后一定要用 free 函数进行释放, 防止内存泄露。

12、选择好的无限循环

在编程中,我们常常需要用到无限循环,常用的两种方法是while (1) 和 for (;;)。这两种方法效果完全一样,但那一种更好呢?然我们看看它们编译后的代码:

编译前:

while (1);

编译后:

mov eax,1test eax,eaxje foo+23hjmp foo+18h

编译前:

for (;;);

编译后:

jmp foo+23h

显然,for (;;)指令少,不占用寄存器,而且没有判断,跳转,比while (1)好。

13、使用Memoization,以避免递归重复计算

考虑Fibonacci(斐波那契)问题,Fibonacci问题是可以通过简单的递归方法来解决:

[plain] view plain copy print?int fib ( n ){if ( n == 0 || n == 1 ){return 1;}else{return fib( n - 2 ) + fib ( n - 1 );}}

注:在这里,我们考虑Fibonacci 系列从1开始,因此,该系列看起来:1,1,2,3,5,8,…

注意:从递归树,我们计算fib(3)函数2次,fib(2)函数3次。这是相同函数的重复计算。如果n非常大,fib函数的效率会比较低。Memoization是一个简单的技术,可以被用在递归,加强计算速度。fibonacci 函数Memoization的代码如下:

[plain] view plain copy print?int calc_fib ( int n ){int val[ n ] , i;for ( i = 0; i 《=n; i++ ){val[ i ] = -1; // Value of the first n + 1 terms of the fibonacci terms set to -1}val[ 0 ] = 1; // Value of fib ( 0 ) is set to 1val[ 1 ] = 1; // Value of fib ( 1 ) is set to 1return fib( n , val );}

int fib( int n , int* value ){if ( value[ n ] != -1 ){return value[ n ]; // Using memoization}else{value[ n ] = fib( n - 2 , value ) + fib ( n - 1 , value ); // Computing the fibonacci term}return value[ n ]; // Returning the value}

除了编程上的技巧外,为提高系统的运行效率,我们通常也需要最大可能地利用各种硬件设备自身的特点来减小其运转开销,例如减小中断次数,利用DMA传输方式等。

对于嵌入式系统,C语言在开发速度,软件可靠性以及软件质量等方面都有着明显的优势。本文就嵌入式C语言在系统开发中,如何更好的利用系统资源,对代码进行优化进行了讨论。当然代码优化的方法还有很多,这里只是写出了一部分,希望能为开发人员提供一些帮助,也欢迎大家留言交流。
编辑:lyn

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5209

    文章

    20645

    浏览量

    336910
  • C语言
    +关注

    关注

    183

    文章

    7646

    浏览量

    146124
  • 代码
    +关注

    关注

    30

    文章

    4976

    浏览量

    74370
  • 算法优化
    +关注

    关注

    0

    文章

    4

    浏览量

    6432

原文标题:手把手教你嵌入式C语言优化技巧

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何成为一名高薪嵌入式工程师?

    嵌入式,也可以轻松入门。 如果你已经明确好,想要从事嵌入式开发,想要成为一名高薪的嵌入式工程师,那下面这几点建议请好好看看: 一、夯实技术基础 ✅编程语言
    发表于 04-09 09:03

    嵌入式C语言高质量编程:从“能用”到“卓越”的跨越

    只有掌握了嵌入式C硬核的技术,才能够铸就工业级高质量的代码。
    的头像 发表于 03-13 10:18 221次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>语言</b>高质量编程:从“能用”到“卓越”的跨越

    什么是嵌入式应用开发?

    。 · ‌医疗设备‌:如心电图仪、血压计等。 开发工具和技术 嵌入式开发过程中常用的工具包括: · ‌集成开发环境(IDE)‌:用于编写、编译和调试代码。 · ‌编译器‌:将高级语言代码转换为机器语言
    发表于 01-12 16:13

    C语言嵌入式系统编程注意事项-内存操作

    C语言嵌入式系统编程注意事项之内存操作 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/
    发表于 01-04 07:31

    C语言单元测试在嵌入式软件开发中的作用及专业工具的应用

    需要硬件模拟的场景 对于安全关键系统,建议选择支持MC/DC覆盖率分析的框架,如winAMS内置的覆盖率分析工具。 2. 测试流程优化 嵌入式C语言单元测试的典型流程应包括: ‌需求
    发表于 12-18 11:46

    嵌入式应掌握的几种能力

    1. 编程语言 基本掌握嵌入式必备的编程语言C语言为主,C++为辅。在资源有限的情况下,大多
    发表于 12-08 06:05

    C语言嵌入式开发中的应用

    C 语言在汽车电子控制系统开发中的主导地位。 2、设备驱动程序 设备驱动程序是嵌入式系统中连接硬件和软件的桥梁,它负责实现嵌入式系统与外部设备之间的通信和控制。
    发表于 11-21 08:09

    2025年最佳的嵌入式编程语言有哪些呢?

    嵌入式系统是现代科技不可或缺的一部分。它们存在于家用电器、汽车、住宅、医院、商店等各个领域。它们与我们的社会紧密相连。选择合适的语言来构建嵌入式系统对于成功至关重要。那么,2025年最佳的嵌入
    的头像 发表于 11-14 10:27 1756次阅读
    2025年最佳的<b class='flag-5'>嵌入式</b>编程<b class='flag-5'>语言</b>有哪些呢?

    C语言是否会阻碍嵌入式的发展?

    门老朋友:C语言。电子工业已经走过了50多年,而C语言仍然是超过六成嵌入式项目的首选。它驱动着全球数以亿计,甚至以万亿计的设备。但它的统治地
    的头像 发表于 11-14 10:27 523次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>是否会阻碍<b class='flag-5'>嵌入式</b>的发展?

    ElfBoard科普课堂|为什么C语言嵌入式技术领域中的地位难以撼动?

    嵌入式技术领域,“C语言与硬件”的组合,常被比作计算机体系中的“二进制与晶体管”——它们是无数智能设备稳定运行的底层支柱,贯穿了嵌入式应用的核心环节。
    的头像 发表于 11-06 10:00 7115次阅读
    ElfBoard科普课堂|为什么<b class='flag-5'>C</b><b class='flag-5'>语言</b>在<b class='flag-5'>嵌入式</b>技术领域中的地位难以撼动?

    嵌入式需要掌握哪些核心技能?

    : 1)C语言与底层编程 核心地位:C语言嵌入式开发的基石,需精通指针操作、内存管理、位运算,直接操控硬件资源。 延伸技能:
    发表于 10-21 16:25

    C语言入门(硬件嵌入式那种不是APP开发的)

    C语言入门(硬件嵌入式那种不是APP开发的),有没有对初学者很友好的书籍、视频等资料推荐一下,一直以来看了正dian原子、野火等的视频、文档结果从快要入门到放气,然后再从放气到快要入门,一直没有进展,还望指点迷津,感谢
    发表于 09-27 12:03

    入行嵌入式应该怎么准备?

    知识: 一、C/C++编程C/C++是嵌入式系统开发中最常用的编程语言。熟练掌握
    发表于 08-06 10:34

    Linux嵌入式和单片机嵌入式的区别?

    : 单片机嵌入式 :开发环境相对简单,通常使用C语言或汇编语言进行编程,开发工具包括Keil、IAR等。 Linux嵌入式 :开发环境较
    发表于 06-20 09:46

    嵌入式开发入门指南:从零开始学习嵌入式

    特定功能的计算机系统,广泛应用于智能家居、工业控制、医疗设备、车载系统等领域。 2. 学习嵌入式开发的前置知识熟悉C语言编程掌握基本的数据结构与算法了解数字电路与微控制器原理熟悉Linux操作系统
    发表于 05-15 09:29