新闻  |   论坛  |   博客  |   在线研讨会
嵌入式程序设计中C/C++代码的优化
jinren1010 | 2008-04-28 17:15:19    阅读:3257   发布文章

摘要:本文介绍了在嵌入式程序设计中几种提高C/C++代码效率的方法,通过对例子的分析,探讨了影响程序效率的原因。
关键词:c语言,c++,嵌入式,优化

1  引言
    嵌入式计算机系统是指完成特定功能的计算机系统,它具有软件代码小,自动化程度高,响应速度快等特点。特别适合于要求实时和多任务的应用体系。由于嵌入式系统受时间、空间和运行环境的严格限制,使得嵌入式系统软件的开发变得非常困难,为了开发出高性能的嵌入式系统,开发语言的选择十分关键。
    目前,在嵌入式系统开发过程中可使用的语言很多,其中C和C++应用得最广泛。C++在面向对象、结构化等方面对C进行了改进,但在程序代码容量、执行速度等方面性能不如C语言。C语言既有低级语言的直接控制硬件的能力,又有高级语言的灵活性,在嵌入式系统中得到了最广泛的应用。在嵌入式的系统开发中,出于对低价产品的需求,硬件的设计者需要提供刚好足够的存储器和完成工作的处理能力。所以在嵌入式软件设计的最后一个阶段变成了对代码的优化阶段。
    经过本人在嵌入式系统设计过程中的实践,下面介绍几种简单且行之有效的C/C++代码的优化方法。考虑到读者已经学过了C/C++的原理,有一些已经是经验丰富的编程员,本文的叙述将尽可能****。

2  变量的处理
    开始编程时,一般首先遇到的是初始化的问题。建议使用英文单词的缩写代表变量,比如代表高度指针的变量可取名highpoint 或简写为hiptr。用缩写减少字母可加快程序的运行速度并减少占用的内存。另外变量类型选取的范围越小运行速度越快占用的内存越少。比如int型变量比long型变量运行速度越快,但变量类型选取的范围越小算术运算时越容易产生溢出错误。
    在声明局部变量的时候可以使用寄存器变量register关键字。这就使得编译器把变量放入寄存器中,而不是在堆栈中,合理使用这种方法可以提高执行速度。函数调用越频繁,提高代码的效率越明显。
当使用变量作为函数返回值时,当变量值很大时,将花费很多的复制时间。参数返回没有变量返回的复制时间的问题,在时间上要快。但参数返回破坏了参数值,在安全性能上和函数的重复使用性能上差。建议在编程时,小的常量返回可用变量,小的变量返回用指针,大的常量返回可用参数或静态方法。另外,使用全局变量比函数传递参数更加有效率。这样做去除了函数调用参数入栈和函数完成后参数出栈所需的时间。然而,决定使用全局变量会影响程序的模块化和重入,故要慎重使用。

3  数组的处理
    (1)数组在使用前需要对其先初始化。一种提高速度的方法是数组的范围在初始化时空着不添,这样程序运行的速度会更快。以函数引用数组为例:
void p(int a[6][3]){
for(int j=0;j<2;j++)
a[j][2]=j;
}
与之对应的函数
void p(int a[][3]){
for(int j=0;j<2;j++)
a[j][2]=j;
}
    两种编程方法产生的结果完全相同,后一种方法由于数组[]内的数字不添,在执行时将由数组自动加入,结果会使程序运行的速度更快。同时也避免由于事前初始化数组时定义的范围过大而带来不必要的存储器浪费。
    (2)用指针代替数组,这样做常常能产生又快又短的代码。与数组索引相比,指针一般能使代码速度更快,占用空间更少。指针方法的优点是装入地址后,在每次循环中,只需增量操作。而在数组索引方法中,每次循环中都必须进行基于数组下标的复杂运算。
    (3)enum 方法常用于处理字符串数组。它有两个特点:(1)使数组中数自动排列(2)将数组中的数和字符串一一对应,以后处理字符串时使用相应的数字。enum使字符串的处理以数字的速度运行,而数字的处理速度比字符串的要快得多。enum的另一优点是自动加一。举例来说:
enum Months{JAN=1,FEB,MAR,APR,MAY}。
    定义一个数字串数组Months,当数组的第一个变量赋值为1时,其它变量自动加一(FEB=2,MAR=3,-----)。

4  算数运算
    简化数学表达式可以提高运算速度,这是一个基本的常识。下面举几个简化数学运算的例子:
    (1) int a=a*b + a*c;
    将程序改为:
int a=a*(b + c);
两种编程方法产生的结果相同,后一种方法由于等号右边减少了一次乘法运算,节省了时间加快了速度。
(2) int a=2,b=256;
a= a*32+b/64;
    将程序改为:
int a=2, b=256;
a=(a<<5)+(b>>6);
    两种编程方法在逻辑上完全相同,因为但通过移位进行2的整数次幂的乘除法要比直接进行乘除法运算速度快,所以后一种编程所需的运算时间短。
    (3) int d=a/c+b/c;
     与之对应的
int d=(a+b)*(1/c)
    在不改变表达式含义的情况下,因为乘法运算比除法运算的度快,所以后一个表达式运算的速度快。
 (4)如果精度许可,运算数据的位数选取应尽量短。当运算的数据超过CPU一次所能处理的最大数据时,CPU在系统管理下一般会对位数超过的大数自动分割处理,但这会使运算速度减慢。比如在16位机中,如果两相加数的位数都小于或等于15位,两数的运算在CPU中都可一次完成。当两相加数的位数都为17位时,两数的运算在CPU中需两次才能完成。在精度许可的前提下,如果想减少运算时间,应尽量使两个数的运算在CPU中一次完成,以提高运算速度。从存储 方面来说,存储数据的位数大将使存储控制器的负担过重,使它的处理速度变慢。需要注意的是,位数过大的数在存储器中造成的运算速度变慢的情况常常比在CPU中更严重。

5  函数调用
    函数调用属于嵌套,分层的优秀编程方法,但它使程序处理的时间长,同时它占用的内存较多,同时使运算速度变慢,即它这一方法是有代价的。先说函数调用,
int d=appl(5,4,3); 
int appl(int a,int b,int c){
int d=a*b*c;
return d;
}
在逻辑上这就等同于
int a=5, b=4, c=3;
int d=a*b*c;
    第二个种方法运行的速度快,但灵活性差,不便于管理。将函数调用改为大的单一程序虽然使程序运行的速度更快,但编写,调试和维护是很不容易的。
     再举例来说,调用一次函数int add1(int a, int b ){return a= a*a + b*b}等同于重复调用两次函数int add2(int a){return a=a*a;}然后再相加两次调用的结果。但调用两次add2函数需分别在内存中建立和释放两次资源,所用的时间要比调用一次函数增加近一倍。所以编程时,需要考虑如何在方便的调试维护和程序运行效率之间寻找平衡点。
5、1  If函数
    在条件语句的判别中,先执行前面的判别,如果条件不满足再执行后面的判断。建议你将出现可能性最大的条件放在前面,举例来说,如果出现的x数值为1-100中的任何一个数,并且概率相同。
if(x>5){   int x=6;  }
else if(x<5){  int x=4;  }
else (x==5){  int x=5;  }
    上面的程序,当产生的x数值为6-100之间时(这种可能性最大),满足第一个条件后计算机就直接从上述程序中返回而不再执行第二和第三个判别了,即多数情况下程序只判别一次就返回了,节省了运行的时间。
    如果条件语句中存在逻辑判断时,判断的顺序是从左至右。比如:if(x>20&&x<30);计算机首先判断是否x>20成立,如果成立再判断是否x<30成立。在x<20出现的概率较大时,应将x<20放在前面。上述安排使计算机在多数(x<20)的情况下直接得出结果,避免浪费时间的进一步判别,以此提高运算速度。因为等号右边的表达式在等号左边的为假时将不再计算,因为此时整个表达式的值已不可能为真。

5、2  Inline函数
    在C++中,关键字inline 用于处理函数。可以被加入到任何函数的声明中。这个关键字请求编译器用函数内部的代码替换所有对于指出的函数的调用。这样做在两个方面快于函数调用:第一,省去了调用指令需要的执行时间;第二,省去了传递变元和传递过程需要的时间。inline 关键字告诉编辑器在适当的地方拷贝函数,它的作用有点象C++的宏,有了它你可节省函数调用的额外开销,它属于一种折中方案一般只在频繁调用的小函数上使用,比如:
inline double cub(int s){
return s*s*s;
}
    inline将函数cub(int s)生成一系列的函数拷贝代码并插入到程序中的适当地方。当你反复调用cub(int s)函数时,你将分别调用不同的cub(int s)函数拷贝代码,而不是反复地调用同一个函数,这样可减少程序的运行时间,但会使程序变大,并且需要更多的ROM。

6  结论
    在嵌入式实时程序设计代码中可能隐藏很多额外的开销,一些变量、数组和函数看似简单、私下里却执行着复杂的工作,消耗着大量的资源。在编程时,应尽量优化自己的程序,减少不必要的运算,如果有多种编程方法可完成同一功能,应尽量选择一种使程序最简洁,高效的方法。简洁、高效优化的编程原则被一些程序员称之为KISS原则(Keep it simple and simple翻译中文为尽量使程序简洁再简洁,资源占用尽量少同时速度尽量快)。

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
老菜鸟  2008-04-28 17:55:26 

写的很好,谢谢分享

推荐文章
最近访客