首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

高效C代码的编写 (转)(2)

高效C代码的编写 (转)(2)

i) 嵌套的if语句:

if (STATUS = = A) React_A();

else if (STATUS = = B) React_B();

else if ....
ii) switch-case
语句:

switch (STATUS)
case (A): React_A(); break;
case (B): React_B(); break;
...
iii)
函数指针: (假定状态A, B, ... 是顺序编号的值,或是枚举类型值)
void React_Func[] = {React_A, React_B, ...};
...
React_Func[STATUS]();

具体采用哪种方式,依据反复次数而定。表2给出了不同方法对ROMRAM空间的占用情况。从中可看出“switch”方式的可读性最强,但在反复次数少(函数个数少)的情况下,占用的空间最大。

“if”
方式的可读性较好,占用的空间也比较小。而“pointer”方式占用ROM的空间相对变化不大,但占用许多RAM空间。
存储模式和零页的使用

不同的MCU有不同的存储模式。在CodeWarrior for HC(S)08 (V3.1),建立工程的时候有smalltiny两种模式可供选择:SMALL模式,如果没有特殊的说明,所有的指针和函数地址都被假定为16位的地址,此模式中代码和数据都被存储在64k的地址空间内;TINY 模式,所有的数据包括堆栈都分配在零页地址空间内,如果没用关键字_far作特殊说明,所有数据指针都被假定为8位地址,但是代码的地址空间仍然是64k,函数指针也仍是16位的长度。
前面讨论中说过,变量放在零页地址内生成的代码较少,而且能有效的支持位运算。在HC(S)08系列单片机中,外围寄存器一般占用$00$3F的地址空间,所以留给RAM的零页地址空间是有限的。为了缩减生成的代码,就要把频繁使用的变量放在零页内。要根据子程序、函数参数和局部变量使用的情况,确定堆栈的使用频率,如果频率高就把堆栈放置在零页地址内。减少生成的代码,我们也要减少子程序中的参数(因为要用到AHX寄存器),把经常使用的临时变量定义成全局变量放在零页地址中。当然,全局变量是共享的,所以用的时候我们要格外小心。下面的例程中,Calc()函数中,可以改变全局变量gTemp2gTemp3的值,但不能改变变量gTemp1的值,因为一开始就对子程序进行了这个设定。通常,好的变量名可以帮我们清楚的区分变量的作用范围。比如分别以123结尾的变量,可以设定等级1的子程序只能用1结尾的变量,等级2的子程序只能用23结尾的变量。

uint8_t gTemp1, gTemp2, gTemp3;     //
存放临时数据的全局变量,所有函数都可以访问
void_t Calc( uint8_t in) {
   gTemp3 = 0 ;
   for (gTemp2 = 5 ; gTemp2 !=0 ; gTemp2--) gTemp3 += ADCR * t_in;
}

void main( ) {
...
for (gTemp1 = 0; gTemp1 < 3; gTemp1++)
  Calc(array[gTemp1]) ;

...
}

初始化的优化
CodeWarrior,每个工程都有一个模板,Start-up启动函数已经预先写好,我们可以在建工程的时候选择是否采用ANSI标准初始化程序。通常,标准初始化程序的代码效率并不高(可以参看start08.c文件中的源程序)。为了减少生成的代码,我们应该采用非ANSI标准的初始化程序,由用户自行编写。比如,仅做堆栈指针初始化、RAM清空和跳转到main函数三项工作,用如下汇编代码实现。
asm {
       clra                          ;
得到清零数据
        ldhx    #MAP_RAM_last        ;
指向RAM的尾部
        stx    MAP_RAM_first         ;
使得RAM起始地址内的数值非零
       txs                           ;
初始化堆栈指针
ClearRAM:
       psha                          ;
清空当前RAM地址
        tst    MAP_RAM_first         ;
检测是否完成RAM的清空
        bne    ClearRAM             ;
没有完成就继续

       txs                           ; 初始化堆栈指针
        jmp    main                 ;
跳转到main()函数
}

除了这些通用的起始程序,还需要对硬件和变量进行初始化。尽管寄存器都有默认值,但仍要培养用软件对硬件初始化的好习惯。对于变量,最好初始值为零,因为清空RAM代码已经完成了这个工作。为了防止代码臃肿,建议把相同初始值的变量归为一组,这样可以用循环的方式对它们进行初始化。在优化代码的时候,要特别注意那些可变型volatile变量(比如寄存器),因为编译器是不会对这些变量进行优化的。

结语

本文简述了一些优化代码的方法,包括变量的选择、使用静态类型、数组和指针的挑选、如何使用存储模式和如何进行初始化等。但是,这仅是所有方法的一部分。一个高效的C语言程序,不仅要代码少、执行速度快,而且要清楚、简洁、准确和易注释。此外,程序要有一个好的架构,便于移植和维护。代码的再使用性(reuse)也是一个关键因素,这不在于代码本身,而在于它能减少开发调试时间。所以说,高效的C语言程序是各种因素的综合体,需要我们全面考量。
继承事业,薪火相传
返回列表