SN单片机c程序优化方法

来源:互联网 发布:新代数控车床编程实例 编辑:程序博客网 时间:2024/05/22 05:09

SONIX单片机C语言程序优化方法,对其他类型的单片机应该也会有一些借鉴作用
资料来源:SONIX单片机C语言编译器《SN8 C studio》里的帮助文档

1、如果在定义或声明变量为int数据类型时足够,请勿使用关键字“long”。 以同样的方式,如果浮动的精度足够,不要使用“double”。
2、如果声明一个通用指针,当程序中使用指针时,需要对指针指向RAM或ROM进行判断。 但是使用ram / rom指针可以避免这个额外的动作!

int* pInt;int g;void main(){    pInt = &g1;    g = 1;    if(*pInt != 1)    return 1;    return 0;}Rom has used : 93 [0x5D] words----------__RAM int* pRam;int g;int main(){    pRam = &g;    g = 1;    if(*pRam != 1)    return 1;    return 0;}Rom has used : 79 [0x4F] words

3、如果一个标志只有两个状态:0或1,可以采用位数据类型而不是int类型。 因为位类型的操作比int类型更简单,所以会产生较少的指令。 此外,位变量占用的内存比int变量少。
4、因为操作多维数组是复杂的,所以C编译器必须生成大量的指令来实现多维数组操作。所以没事不要用多维数组。
5、通常,当使用int数据类型时,C编译器将生成一些处理否定条件的指令,但是对于数组,大多数这些指令是无用的。 所以用户可以使用unsigned类型来避免这个问题。

int a[10];int main(void){     int i;    for(i = 0;i<=9;i++)    a[i] = 1;}Rom has used : 73 [0x49] words--------------------int a[10];int main(void){     unsigned i;    for(i = 0;i<=9;i++)    a[i] = 1;}Rom has used :70 [0x46] words

6、如果全局变量位于ram bank 0中,则不需要生成额外的指令来更改RBANK寄存器。

#pragma rambank 1int g_i, g_j,g_k;int main(void){    int i,j,k;    i = 1;    g_i = 1;    j = 1;    g_j = 1;    k = 1;    g_k = 1;}Rom has used : 69 [0x45] words---------------------#pragma rambank 0int g_i, g_j,g_k;int main(void){    int i,j,k;    i = 1;    g_i = 1;    j = 1;    g_j = 1;    k = 1;    g_k = 1;}Rom has used : 64 [0x40] words

7、由于位数据类型的操作比指针简单,使用位参考类型而不是指针是减少代码大小的更好方法。

#include<sn8p2708a.h>int main(void){    if(FP4CON2 != FP4CON3)    return 1;    else     return 0;}Rom has used : 76 [0x4C] words----------------------#pragma data_address 0xae:2sbit fpcon2;#pragma data_address 0xae:3sbit fpcon3;int main(void){    if(fpcon2 != fpcon3)    return 1;    else     return 0;}Rom has used : 62 [0x3E] words

8、因为位数据类型的操作比位字段更简单,所以使用位参考类型而不是位归档是减少代码大小的更好方法。也就是直接位定义,而不需要把位归类。

struct BitField{    unsigned int bit0:1;    unsigned int bit1:1;    unsigned int bit2:1;    unsigned int bit3:1;    unsigned int bit4:1;    unsigned int bit5:1;    unsigned int :2;};int main(void){    struct BitField bitfield;    bitfield.bit0 = 1;    if(bitfield.bit1==1)    bitfield.bit2 = 0;    if(bitfield.bit3!=0)    bitfield.bit3 = 0;}Rom has used : 73 [0x49] words ------------------------int bitfield;int main(void){    sbit bit0 = bitfield:0;    sbit bit1 = bitfield:1;    sbit bit2 = bitfield:2;    sbit bit3 = bitfield:3;    bit0 = 1;    if(bit1==1)    {        bit2 = 0;    }    if(bit3!=0)    {        bit3 = 0;    }}Rom has used : 64 [0x40] words

9、为了实现相同的功能,使用变量会产生比指针少的指令。 所以不要尽可能使用指针。

int main (void){     int i;     int *p = &i;    *p= 1;}Rom has used : 62 [0x3E] words--------------------------int main (void){     int i;     int *p = &i;    i = 1;}Rom has used : 58 [0x3A] words

10、如果在程序中多次使用指针,其值不会频繁更改,则可以使用变量作为替代来完成相同的工作。

#include<sn8p2708a.h>int main(void){    int temp = R;    int i = 2;    int j = temp*i;    int k = temp*j;}Rom has used : 71 [0x47] words-----------------------#include<sn8p2708a.h>int main(void){    int i = 2;    int j = R*i;    int k = R*j;}Rom has used : 69 [0x45] words

11、当使用“++ / - ”和其他运算符在一起时,首先编译器将变量的值增加到寄存器之前或之后,然后获取寄存器的值开始其他操作,因此大量的冗余代码 将被生成,所以最好只使用“++ / - ”!

#include<sn8p2708a.h>int main(void){     long i;    if(++i == 10)     i = 0;}Rom has used : 74 [0x4A] words---------------------------#include<sn8p2708a.h>int main(void){     long i;    i++;    if(i == 10)    i = 0;}Rom has used : 64 [0x40] words

12、有一个关于每个类型的乘法代码大小的序列:unsigned <int <long <float.So对于代码大小的考虑,用户将选择数据类型的最小大小来声明变量。这里就不举例了。


13、有一个关于每个类型的除法的代码大小的序列: unsigned <= int(char)<long <float .So为代码大小的考虑,用户将选择最小的数据类型大小来声明变量。乘法和除法还是有点区别的。
14、在某些时候,如果将int和float数据类型的乘法结果分配给一个int变量,为了避免加载Std库并获得相同的结果,有一个消费建议将float数据类型转换为int。

int main(void){    int i1 = 12;    int i2 =i1 * 2.0;}Rom has used :472 [0x1D8] words-------------------------------------int main(void){    int i1 = 12;    int i2 =i1 * 2;}Rom has used : 56 [0x38] words

15、有时候,如果将int和float数据类型的除法结果分配给int变量,为避免加载Std库并获得相同的结果,尽可能的将float数据类型转换为int。

int main(void){    int i1 = 12;    int i2 =i1 /3.0;}Rom has used : 472 [0x1D8] words--------------------------int main(void){    int i1 = 12;    int i2 =i1/ 3;} Rom has used : 56 [0x38] words

16、将int ant float类型转换为尽可能与int类型相关的除法,因为实现int和float的乘法比int类型的分割更复杂! 例如:

int main(void){     int i= 2;    int j = i*0.5;} Rom has used : 461 [0x1CD] words----------------------int main(void){     int i= 2;    int j = i/2;}Rom has used : 120 [0x78] words

17、通常,乘法的代码大小小于相同数据类型的除法,因此尽可能地将分割转换为乘法。

int main(void){     float i= 2.0;    float j = i/2.0;}Rom has used : 418 [0x1A2] words----------------------------int main(void){     float i= 2.0;    float j = i*0.5;}Rom has used : 387 [0x183] words

18、如果赋给int变量赋值的结果,并且涉及浮点类型的加法。有一个很好的建议将float类型转换为int,因为这里使用float类型在大多数时候是无用的!

int main(void){    int i1 = 12;    int i2 =i1 + 2.0;}Rom has used : 472 [0x1D8] words------------------------------int main(void){    int i1 = 12;    int i2 =i1 + 2;}Rom has used : 56 [0x38] words

19、如果将减法的结果分配给int变量,并且涉及浮点型的相加。 有一个很好的建议来将float类型隐藏为int,因为在这里使用float类型在大多数时候是无用的!

int main(void){    int i1 = 12;    int i2 =i1 – 3.0;}Rom has used : 74 [0x4A] words----------------------------------int main(void){    int i1 = 12;    int i2 =i1 - 3;}Rom has used : 71 [0x47] words

20、一般来说,“<<”的操作比“*”简单,所以采取“<<”而不是“*”是减少代码大小的好主意。

int main(void){    long i = 2;    i = i * 64;}Rom has used : 82 [0x52] words----------------------------------int main(void){    long i = 2;    i = i << 6;}Rom has used : 62 [0x3E] words

21、一般来说,“>>”的操作比“/”简单,所以取代“/”代替“>>”是减少代码大小的好主意。

int main(void){    long i = 264;    i = i/64;}Rom has used : 183 [0xB7] words--------------------------int main(void){    int i = 264;    i = i>>6;}Rom has used : 65 [0x41] words

22、一般来说,“&”的操作比“%”简单,所以采用“&”代替“%”是减少代码大小的好主意。

int main(void){    int i = 6;    int j = i%8;}Rom has used : 120 [0x78] words--------------------------------int main(void){    int i = 6;    int j1 = i&7;}Rom has used : 56 [0x38] words

23、如果芯片不支持MUL指令,则C编译器将加载Std库以完成此工作。 为了避免这种复杂的操作,它是尽可能地使用加法而不是简单乘法的更好的方法。

int main(void){    int i, j;    i = i * 3;}Rom has used : 82 [0x52] words--------------------------int main(void){    int i, j;    i = i + i + i ;}Rom has used : 59 [0x3B] words

24、如果compare的操作在integer和const之间,对于代码大小的考虑,可以将const更改为const +1,并使用“> =”而不是“>”。

int main(void){    int i1 = 12;    int i2 = 0;    if(i1 > 10)    i2 = 1;}Rom has used : 63 [0x3F] words------------------------------int main(void){    int i1 = 12;    int i2 = 0;    if(i1 >= 11)    i2 = 1;}Rom has used : 61 [0x3D] words

25、如果compare的操作在integer和const之间,对于代码大小的考虑,可以将const更改为const + 1并使用“<”而不是“<=”。

int main(void){    int i1 = 12;    int i2 = 0;    if(i1 <= 10)    i2 = 1;}Rom has used : 66 [0x42] words------------------------------int main(void){    int i1 = 12;    int i2 = 0;    if(i1 < 11)    i2 = 1;}Rom has used : 61 [0x3D] words

26、对于位变量,“〜”的操作比“!”简单,所以取“〜”而不是“!” 是减少代码大小的好主意。

int main(void){    bit i,j;    i = 0;    j = !i;    if(j == 0)    return 1;    return 0;}Rom has used : 82 [0x52] words--------------------------------int main(void){    bit i,j;    i = 0;    j = ~i;    if(j == 0)    return 1;    return 0;}Rom has used : 71 [0x47] words

27、对于长表达式,c编译器将生成一些临时变量来存储子表达式的值。 我们可以将复杂的操作分解成简单的语句序列。

int main(void){     int a;    int b;    int c;    int d, e;    e = (a + b) * c * a + b;}Rom has used : 66 [0x42] words---------------------------int main(void){     int a, b, c, d, e;     e = a + b;    e *= c;    e *= a;    e += b;}Rom has used : 60 [0x3C] words

28、对于复杂的if语句,c编译器将生成一些临时变量来存储一些子条件的值。 我们可以将复杂的操作分解成简单的语句序列。

int main(void){    int a,b,c;    if(a == b && b == c && a != c )    ;}Rom has used : 70 [0x46] words------------------------------int main(void){    int a,b,c;    if(a==b)    if(b == c)    if(a != c)    ;}Rom has used : 64 [0x40] words

29、有时候,调整框架的“if”语句可以减少代码大小,例如:

#include<sn8p2708a.h>int main(void){    int i,j;    int flag;    if(flag)    i = 0;    else    i = 1;}Rom has used : 59 [0x3B] words--------------------------------#include<sn8p2708a.h>int main(void){    int i, j;    int flag;    i = 1;    if (flag)    i = 0;}Rom has used : 58 [0x3A] words

30、对于c源代码,编译器的条件表达式的语法树比“if else”语句更复杂,因此编译器可以比“if else”语句的条件表达式生成更少的指令来实现该函数。

#include<sn8p2708a.h>int main(void){     int i;    i = FP27M ? 1:0;}Rom has used : 60 [0x3C] words------------------------------------#include<sn8p2708a.h>int main(void){     int i;    if(FP27M) i = 1;    else i = 0;}Rom has used : 58 [0x3A] words

31、编译器可以根据条件编译选择正确的语句,因此是减少代码大小的好方法。

int LETTER = 1; void main() {     char str[20]="C Language";    char c;     int i=0;     while(i<=19)    {         c = str[i];        if (LETTER == 1)        if(c>='a'&& c<='z') c=c-32;         else         if(c>='A'&& c<='Z') c=c+32;         str[i] = c;        i++;     } }Rom has used : 144 [0x90] words-------------------------------------------------#define LETTER 1 void main() {     char str[20]="C Language";    char c;     int i=0;     while(i<=19)    {         c = str[i];        #if LETTER         if(c>='a'&& c<='z') c=c-32;         #else         if(c>='A'&& c<='Z') c=c+32;         #endif         str[i] = c;        i++;     } }Rom has used : 124 [0x7C] words

32、当程序中使用多层“if else”语句时,建议使用“switch”语句而不是多层。 如果“switch”语句满足跳转表的条件,则编译器将为此生成较少的指令。

int main(void) {     int i, test = 1;    if(test == 0) i = 0;    else if (test == 1)         i = 1;    else if (test == 2)         i = 2;    else if (test == 3)         i = 3;    else if (test == 4)         i = 4;    else if (test == 5)         i = 5;    else if(test == 6)        i = 6;    else if(test ==7)        i = 7;    else if(test == 8)         i = 8;}Rom has used : 106 [0x6A] words---------------------int main(void){ int i; int test = 1;switch (test) {    case 0: i = 0;    break;    case 1: i = 1;    break;    case 2: i = 2;     break;    case 3: i = 3;     break;    case 4: i = 4;     break;    case 5: i = 5;     break;    case 6: i = 6;    break;    case 7: i = 7;     break;    case 8: i = 8;     break; }}Rom has used : 102 [0x66] words

33、如果“switch”语句不符合跳转表的条件,则编译器会生成比if else语句更多的指令。

void main( ){    int i = 1;    switch (i){        case 1: i=1;        break;        case 25: i=2;         break;        case 43: i=3;        break;        case 102: i=4;         break;        case -6: i=5;         break; }}Rom has used : 106 [0x6A] words------------------------------void main(){    int i = 1;    if (i==1)        i=1;    else if (i==25)        i=2;    else if (i==43)        i=3;    else if (i==102)        i=4;    else if (i==-6)        i=5;}Rom has used : 82 [0x52] words

34、避免在if / while / for中的函数调用,因为在“if / while / for”中的函数调用将生成隐式变量

int fun (void){    int i = 0;    return i;}int main (void){     int i;    if(fun() == 0)        i = 0;    else if (fun() == 1)        i = 1;    else if (fun() == 2)        i = 2;}Rom has used : 75 [0x4B] words------------------------int fun(void){    int i = 0;    return i;}int main(void){     int i, temp = fun();    if (temp== 0)        i = 0;    else if (temp == 1)        i = 1;    else if (temp == 2)        i = 2;}Rom has used : 73 [0x49] words

35、当在中断功能中调用其他函数时,编译器需要生成一组操作,以便在发生中断时保存和恢复环境。 所以直接在中断函数中编写代码,以避免编译器尽可能的做这个繁琐的工作!

void fun(){    __asm    {        MOV A, #0x01        B0MOV RBANK, A;    }}__interrupt interruptfun(){    fun();}void main(void){}Rom has used : 126 [0x7E] words-------------------__interrupt interruptfun(){__asm    {        MOV A,#0x01        B0MOV RBANK A;    }}void main (void){}Rom has used : 64 [0x40] words

36、如果在程序中频繁使用某些操作,则将它们收集到一个函数中是减少代码大小的一种可行的方法。

int array[10][10];int main(void){    int i,j;    for(i = 0;i <= 9; i++)        for(j = 0;j<= 9; j++)            array[i][j] = 0;    // do other something}int fun(void){    int i,j;    for(i = 0;i <= 9; i++)        for(j = 0;j<= 9; j++)            array[i][j] = 0;    // do other something}Rom has used : 180 [0xB4] words------------------------------int array[10][10];void init_array(void){    int i, j;    for(i = 0;i <= 9; i++)        for(j = 0;j<= 9; j++)            array[i][j] = 0;}int main(void){    init_array();    // do other something}int fun(void){    init_array();    // do other something}Rom has used : 129 [0x81] words

37、在函数中使用参数时,首先编译器必须将参数输入到参数中。 然后使用参数传递值,但是使用全局变量可以避免这个额外的动作来实现相同的功能

int fun(int g_i,int g_j){    int i = g_i;    int j = g_j;}int main(void){    int i, j;    fun(i, j);}Rom has used : 64 [0x40] words--------------------------------int g_i, g_j;int fun (void){    int i = g_i;    int j = g_j;}int main(void){    fun();}Rom has used : 60 [0x3C] words

38、传递类型为struct或union的参数的地址将节省更多的代码大小。 否则,它需要更多的代码大小为结构或联合的副本。

typedef struct Solstruct{    int i;    int j;    int k;    int q;}Sstruct;void fun(struct Solstruct s){}int main(void){    struct Solstruct s;    fun(s);}Rom has used : 66 [0x42] words-------------------------------typedef struct Solstruct{    int i;    int j;    int k;    int q;}Sstruct;void fun(struct Solstruct *s){}int main(void){    struct Solstruct s;    fun(&s);}Rom has used : 58 [0x3A] words

39、如果函数不需要返回值,请将其声明为void类型,因为如果函数不是void类型,那么编译器会生成一些有关返回值的代码

int fun(void){    return 1;}int main(void){    fun();    return 0;}Rom has used : 56 [0x38] words--------------------------------void fun(void){} int main(void){    fun();    return 0;}Rom has used : 54 [0x36] words

40、在程序中使用函数指针时,它比函数更复杂,所以不要尽可能使用它。

void (*funptr)();void fun(void){}int main(void){    funptr = fun;    funptr();}Rom has used : 82 [0x52] words-----------------------------void (*funptr)();void fun(void){}int main(void){    funptr = fun;    fun();}Rom has used : 58 [0x3A] words

41、例如,由编译器生成的关于多维数组的指令是复杂和冗余的,因此我们可以使用内联汇编器!

#include<sn8p2708a.h>int a[5][5];int main (void){     int i, j;    for(i=0;i<=4;i++)    {        for(j=0;j<=4;j++)        {            a[i][j] = 1;        }    }}Rom has used : 128 [0x80] words-------------------------------#include<sn8p2708a.h>int a[5][5];int main(void){     int i,j;    for(i=0;i<=4;i++)    {        for(j=0;j<=4;j++)        {            __asm{            SelectBank(i)            MOV A, #5            MUL A,CNameToAsmLabel(i)            SelectBank(j)            ADD A,CNameToAsmLabel(j)            ADD A, #(CNameToAsmLabel(a))$L            B0MOV Z,A;            MOV A, #(CNameToAsmLabel(a))$M            B0MOV Y,A            MOV A,#0x01            B0MOV @YZ, A}        }    }}Rom has used : 81 [0x51] words

42、好的算术比一个好的编译器更有效!

void BubbleSort(int* pData,int Count){    int iTemp;    int i,j;    for(i=1;i<Count;i++)    {        for(j=Count-1;j>=i;j--)        {            if(pData[j]<pData[j-1])            {                iTemp = pData[j-1];                pData[j-1] = pData[j];                pData[j] = iTemp;            }        }    }}void main(){    int data[] = {10,9,8,7,6,5,4};    BubbleSort(data,7);}Rom has used : 272 [0x110] words---------------------------void InsertSort(int* pData,int Count){    int iTemp;    int iPos;    int i;    for(i=1;i<Count;i++)    {        iTemp = pData[i];        iPos = i-1;        while((iPos>=0) && (iTemp<pData[iPos]))        {            pData[iPos+1] = pData[iPos];            iPos--;        }        pData[iPos+1] = iTemp;    }}void main(){    int data[] = {10,9,8,7,6,5,4};    InsertSort(data,7);}Rom has used : 241 [0xF1] words