打印

嵌入开发中C可以提高效率和减少代码size的方法

[复制链接]
660|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Dennis-Zhou|  楼主 | 2016-6-28 18:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1 switch-case语句。在程序中经常会使用switch-case语句,每一个由机器语言实现的测试和跳转仅仅是为了决定下一步要做什么,就浪费了处理器时间。为了提高速度,可以把具体的情况按照它们发生的相对频率排序。即把最可能发生的情况放在第一,最不可能发生的情况放在最后,这样会减少平均的代码执行时间。
  2全局变量。使用全局变量比向函数传递参数更加有效率,这样做去除了函数调用前参数入栈和函数完成后参数出栈的需要。当然,使用全局变量会对程序有一些负作用。
  3嵌入式系统编程应避免使用标准库例程,因为很多大的库例程设法处理所有可能的情况,所以占用了庞大的内存空间,因而应尽可能地减少使用标准库例程。
    (1) Inline函数

   在C++中,关键字Inline可以被加入到任何函数的声明中。这个关键字请求编译器用函数内部的代码替换所有对于指出的函数的调用。这样做在两个方面快于函数调用。这样做在两个方面快于函数调用:第一,省去了调用指令需要的执行时间;第二,省去了传递变元和传递过程需要的时间。但是使用这种方法在优化程序速度的同时,程序长度变大了,因此需要更多的ROM。使用这种优化在Inline函数频繁调用并且只包含几行代码的时候是最有效的。

相关帖子

沙发
Dennis-Zhou|  楼主 | 2016-6-28 18:55 | 只看该作者
   (2)用指针代替数组

   在许多种情况下,可以用指针运算代替数组索引,这样做常常能产生又快又短的代码。与数组索引相比,指针一般能使代码速度更快,占用空间更少。使用多维数组时差异更明显。下面的代码作用是相同的,但是效率不一样。
    数组索引               指针运算
    For(;;){                p=array
    A=array[t++];           for(;;){
                                 a=*(p++);
    ......                    ......
    }                       }

   指针方法的优点是,array的地址每次装入地址p后,在每次循环中只需对p增量操作。在数组索引方法中,每次循环中都必须进行基于t值求数组下标的复杂运算。

使用特权

评论回复
板凳
Dennis-Zhou|  楼主 | 2016-6-28 18:58 | 只看该作者
(3)不定义不使用的返回值

    function函数定义并不知道函数返回值是否被使用,假如返回值从来不会被用到,应该使用void来明确声明函数不返回任何值。

    (4)手动编写汇编

   在嵌入式软件开发中,一些软件模块最好用汇编语言来写,这可以使程序更加有效。虽然C/C++编译器对代码进行了优化,但是适当的使用内联汇编指令可以有效的提高整个系统运行的效率。

使用特权

评论回复
地板
Dennis-Zhou|  楼主 | 2016-6-28 19:01 | 只看该作者
    (5)使用寄存器变量

   在声明局部变量的时候可以使用register关键字。这就使得编译器把变量放入一个多用途的寄存器中,而不是在堆栈中,合理使用这种方法可以提高执行速度。函数调用越是频繁,越是可能提高代码的速度。

使用特权

评论回复
5
Dennis-Zhou|  楼主 | 2016-6-28 19:01 | 只看该作者
    (6)使用增量和减量操作符

   在使用到加一和减一操作时尽量使用增量和减量操作符,因为增量符语句比赋值语句更快,原因在于对大多数CPU来说,对内存字的增、减量操作不必明显地使用取内存和写内存的指令,比如下面这条语句:
    x=x+1;
    模仿大多数微机汇编语言为例,产生的代码类似于:
    move A,x      ;把x从内存取出存入累加器A
    add A,1       ;累加器A加1
    store x       ;把新值存回x

   如果使用增量操作符,生成的代码如下:
    incr x        ;x加1
    显然,不用取指令和存指令,增、减量操作执行的速度加快,同时长度也缩短了。

使用特权

评论回复
6
Dennis-Zhou|  楼主 | 2016-6-28 19:02 | 只看该作者
    (7)减少函数调用参数

   使用全局变量比函数传递参数更加有效率。这样做去除了函数调用参数入栈和函数完成后参数出栈所需要的时间。然而决定使用全局变量会影响程序的模块化和重入,故要慎重使用。

使用特权

评论回复
7
Dennis-Zhou|  楼主 | 2016-6-28 19:02 | 只看该作者
    (8)Switch语句中根据发生频率来进行case排序

    switch语句是一个普通的编程技术,编译器会产生if-else-if的嵌套代码,并按照顺序进行比较,发现匹配时,就跳转到满足条件的语句执行。使用时需要注意。每一个由机器语言实现的测试和跳转仅仅是为了决定下一步要做什么,就把宝贵的处理器时间耗尽。为了提高速度,没法把具体的情况按照它们发生的相对频率排序。换句话说,把最可能发生的情况放在第一位,最不可能的情况放在最后。

使用特权

评论回复
8
Dennis-Zhou|  楼主 | 2016-6-28 19:04 | 只看该作者
    (9)将大的switch语句转为嵌套switch语句

   当switch语句中的case标号很多时,为了减少比较的次数,明智的做法是把大switch语句转为嵌套switch语句。把发生频率高的case标号放在一个switch语句中,并且是嵌套switch语句的最外层,发生相对频率相对低的case标号放在另一个switch语句中。比如,下面的程序段把相对发生频率低的情况放在缺省的case标号内。         pMsg=ReceiveMessage();
        switch (pMsg->type)
        {
        case FREQUENT_MSG1:
        handleFrequentMsg();
        break;
        case FREQUENT_MSG2:
        handleFrequentMsg2();
        break;
        ......
        case FREQUENT_MSGn:
        handleFrequentMsgn();
        break;
        default:                      //嵌套部分用来处理不经常发生的消息
        switch (pMsg->type)
        {
        case INFREQUENT_MSG1:
        handleInfrequentMsg1();
        break;
        case INFREQUENT_MSG2:
        handleInfrequentMsg2();
        break;
        ......
        case INFREQUENT_MSGm:
        handleInfrequentMsgm();
        break;
        }
        }
     如果switch中每一种情况下都有很多的工作要做,那么把整个switch语句用一个指向函数指针的表来替换会更加有效,比如下面的switch语句,有三种情况:
        enum MsgType{Msg1, Msg2, Msg3}
        switch (ReceiveMessage()
        {
        case Msg1;
        ......
        case Msg2;
        .....
        case Msg3;
        .....
        }

    为了提高执行速度,用下面这段代码来替换这个上面的switch语句。

        /*准备工作*/
        int handleMsg1(void);
        int handleMsg2(void);
        int handleMsg3(void);
        /*创建一个函数指针数组*/
        int (*MsgFunction [])()={handleMsg1, handleMsg2, handleMsg3};
        /*用下面这行更有效的代码来替换switch语句*/
        status=MsgFunction[ReceiveMessage()]();

使用特权

评论回复
9
Dennis-Zhou|  楼主 | 2016-6-28 19:05 | 只看该作者
     (10)避免使用C++的昂贵特性

     C++在支持现代软件工程、OOP、结构化等方面对C进行了卓有成效的改进,但在程序代码容量、执行速度、程序复杂程度等方面比C语言程序性能差一些。并不是所有的C++特性都是昂贵的。比如,类的定义是完全有益的。公有和私有成员数据及函数的列表与一个 struct 及函数原形的列表并没有多大的差别。单纯的加入类,既不会影响代码的大小,也不会影响程序的效率。但C++的多重继承、虚拟基类、模板、异常处理及运行类型识别等特性对代码的大小和效率有负面的影响,因此对于C++的一些特性要慎重使用,可做些实验看看它们对应用程序的影响。

使用特权

评论回复
10
l科科1987| | 2016-6-28 20:36 | 只看该作者
但在程序代码容量、执行速度、程序复杂程度等方面比C语言程序性能差一些。终于知道为什么c还不会淘汰了

使用特权

评论回复
11
原味_郭| | 2016-6-29 08:36 | 只看该作者
switch的部分学习了,这个优化确实可以增加速度的。

使用特权

评论回复
12
ahhsyf| | 2016-6-29 10:58 | 只看该作者
单片机中,我估计基本没人用过寄存器变量吧,c51好像不支持这个的

使用特权

评论回复
13
enginezhong| | 2016-6-29 17:18 | 只看该作者
问楼主个问题,switch和if,哪个更省空间,效率更高呢

使用特权

评论回复
14
bairurui0713| | 2016-6-30 15:48 | 只看该作者
看指令的设计了,有的mcu中增量和加减都是用一条指令的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

226

帖子

0

粉丝