嵌入式C语言优化小技巧

1 概述

嵌入式系统是指完毕一种或几种特定功能的计算机系统,具有自己主动化程度高,响应速度快等长处,眼下已广泛应用于消费电子,工业控制等领域.嵌入式系统受其使用的硬件以及运行环境的限制,非常注重代码的时间和空间效率,因此选择一种合适的开发语言十分重要.眼下,在嵌入式系统开发中可使用的语言非常多,当中 C语言应用得最广泛.尽管用 C 语言编程具有很多长处,但基于嵌入式系统的C语言和标准 C语言又有非常大差别.接下来我结合嵌入式系统的特点和自己的一些积累,讨论在程序设计中代码优化的一些小技巧.

2 嵌入式C语言的特点

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

3 C代码在程序中的优化

如今的 C 编译器会自己主动对代码进行优化,但这些优化是对运行速度和代码长度的平衡.假设要获得更小且运行效率更高的代码,须要程序猿手工对代码进行优化.

4 变量类型的定义

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

5 算法优化

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

6 适当的使用宏

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

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

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一次.因此第二个函数性能明显比第一个好.

7 内嵌汇编

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

8 提高循环语言的效率

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

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

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++)
{
... ...
} } // 样例 1-2

例 1-1长循环在外层,效率低;例 1-2长循环在内层,效率高.

(2) 假设循环体内有逻辑推断,并且循环次数大,应把循环推断移到循环体外.如例 2-1比例 2-2 多运行了 K-1 次推断,并且因为前者频繁进行推断,打断了循环"流水线"作业,使得编译器不能对循环进行优化处理,降低了效率.

for (i = 0; i < 10000; i++)
{
if (条件)
语句;
else
语句;
} // 样例 2-1 程序简洁但效率低
if (条件)
{
for (i = 0; i < 10000; i++)
语句;
}
else
{
for (i = 0; i < 10000; i++)
语句;
} // 样例 2-2 程序部简洁但效率高

9 提高 switch 语句的效率

switch 语句是 C 语言中经常使用的选择语句, 在编译时会产生if- else- if 嵌套代码,并依照顺序进行比較,发现匹配时,就跳转到满足条件的语句运行.
当 switch 语句中的 case 标号非常多时,为了降低比較的次数,能够把发生频率相对高的条件放到第一位或者把整个 switch 语句转化嵌套 switch 语句.把发生频率高的 case 标号放在最外层的 switch 语句中,发生相对频率相对低的 case 标号放在另外的 switch 语句中.如例 3 中,把发生率高的case 标号放在外层的 switch 语句中,把发生频率低的放在缺省

的(default)内层 switch 语句中.

switch (表达式)
{
case 值1:
语句1: break;
case 值2:
语句2:break;
... ...
/*把发生频率低的放在内层的switch语句中*/
default:
switch (表达式)
{
case 值n:
语句n: break;
case 值m:
语句m: break;
... ...
}
}

样例3 使用嵌套switch语句提高程序运行效率.

10 避免使用标准库

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

11 採用数学方法优化程序

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

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

使用C语言的位操作能够降低除法和取模的运算.在计算机程序中数据的位是能够操作的最小数据单位,理论上能够用“位运算”来完毕全部的运算和操作.因而,灵活的位操作能够有效地提高程序运行的效率.比方用用位操作区取代除法:比方:128 / 8 ->> 128 >> 3;

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

12 存储器分配

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

13 选择好的无限循环

在编程中,我们经常须要用到无限循环,经常使用的两种方法是while (1) 和 for (;;).这两种方法效果全然一样,但那一种更好呢?

然我们看看它们编译后的代码:
编译前:
while (1);
编译后:
mov eax。1
test eax,eax
je foo+23h
jmp foo+18h
编译前:
for (;;);
编译后:
jmp foo+23h

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

14 使用Memoization,以避免递归反复计算

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

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,…

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2UxMjNfemhvdXdlaQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="border: none;" />
注意:从递归树,我们计算fib(3)函数2次,fib(2)函数3次.这是同样函数的反复计算.假设n非常大,fib函数的效率会比較低.Memoization是一个简单的技术,能够被用在递归,加强计算速度.fibonacci 函数Memoization的代码例如以下:

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 1
val[ 1 ] = 1; // Value of fib ( 1 ) is set to 1
return 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语言在系统开发中,怎样更好的利用系统资源,对代码进行优化进行了讨论.当然代码优化的方法还有非常多,这里仅仅是写出了一部分,希望能为开发者提供一些帮助,也欢迎大家留言交流.

浅析嵌入式C优化技巧的更多相关文章

  1. SQL Server优化技巧——如何避免查询条件OR引起的性能问题

    之前写过一篇博客"SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析",里面介绍了OR可能会引起全表扫描或索引扫描的各种案例,以及如何优化查询条件中含有OR的SQL语句的 ...

  2. SQL Server优化技巧——如何避免查询条件OR引起的性能问题

    原文:SQL Server优化技巧--如何避免查询条件OR引起的性能问题 之前写过一篇博客"SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析",里面介绍了OR可能会引起 ...

  3. SQL Server 聚合函数算法优化技巧

    Sql server聚合函数在实际工作中应对各种需求使用的还是很广泛的,对于聚合函数的优化自然也就成为了一个重点,一个程序优化的好不好直接决定了这个程序的声明周期.Sql server聚合函数对一组值 ...

  4. SQL优化技巧

    我们开发的大部分软件,其基本业务流程都是:采集数据→将数据存储到数据库中→根据业务需求查询相应数据→对数据进行处理→传给前台展示.对整个流程进行分析,可以发现软件大部分的操作时间消耗都花在了数据库相关 ...

  5. Java程序性能优化技巧

    Java程序性能优化技巧 多线程.集合.网络编程.内存优化.缓冲..spring.设计模式.软件工程.编程思想 1.生成对象时,合理分配空间和大小new ArrayList(100); 2.优化for ...

  6. 【转】MyEclipse 2015优化技巧

    MyEclipse 2015优化技巧 MyEclipse 2015优化速度方案仍然主要有这么几个方面:去除无需加载的模块.取消冗余的配置.去除不必要的检查.关闭更新. 第一步: 去除不需要加载的模块 ...

  7. [转] Python 代码性能优化技巧

    选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...

  8. Python代码性能优化技巧

    摘要:代码优化能够让程序运行更快,可以提高程序的执行效率等,对于一名软件开发人员来说,如何优化代码,从哪里入手进行优化?这些都是他们十分关心的问题.本文着重讲了如何优化Python代码,看完一定会让你 ...

  9. Python 代码性能优化技巧(转)

    原文:Python 代码性能优化技巧 Python 代码优化常见技巧 代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化. ...

随机推荐

  1. 【Vjudge】P1989Subpalindromes(线段树)

    题目链接 水题一道,用线段树维护哈希值,脑补一下加减乱搞搞……注意细节就过了 一定注意细节…… #include<cstdio> #include<cstdlib> #incl ...

  2. 【python接口自动化】httpUtils

    # coding=utf8 import requests from common.logger import Logger import logging class httpUtils: logge ...

  3. bzoj 2300 [HAOI2011]防线修建 set动态维护凸包

    题目大意 动态删点,求凸包周长 分析 反过来变成动态加点 用set维护平衡树 具体是找到凸包上左右两点 拆开 就可以把左边当作顺时针求的一个凸包,右边当作逆时针求的一个凸包,像栈那样出set就好了 注 ...

  4. angular关于依赖注入

    <html> <head> <title>Angular JS Forms</title> </head> <body> < ...

  5. vue.js源码学习分享(七)

    var _Set; /* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) { // use ...

  6. 转 Python爬虫入门三之Urllib库的基本使用

    静觅 » Python爬虫入门三之Urllib库的基本使用 1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器 ...

  7. yii模板中常用变量总结

    yii模板中常用的一些变量总结. 现有这样一个url:http://www.phpernote.com/demos/helloworld/index.php/xxx/xxx 则通过如下方式获取的值对应 ...

  8. lunix cat tail more等用法

    cat主要有三大功能:  1.一次显示整个文件.  $ cat filename  2.从键盘创建一个文件.  $ cat > filename  只能创建新文件,不能编辑已有文件.  3.将几 ...

  9. 使用 IntelliJ IDEA 开发 Android 应用程序时配置 Allatori 进行代码混淆

    IntelliJ IDEA 提供了非常强大的 Android 开发支持,就连 Google 官方推荐的 Android Studio 其实也是 IntelliJ IDEA 的一个 Android 开发 ...

  10. L1-2. 点赞【求多组数据中出现次数最多的】

    L1-2. 点赞 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持.每 ...