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
- SN单片机c程序优化方法
- 单片机C程序优化
- 如何优化单片机的C语言程序
- C程序优化方法
- 单片机程序优化经验
- 单片机程序优化
- 单片机程序优化经验
- C语言程序优化方法
- 程序优化的方法(C/C++)
- 单片机C语言代码优化
- SN DSP 程序开发
- 单片机流水灯c程序
- 单片机c语言延时程序
- 单片机c程序反复执行
- 51单片机串口C程序
- msp430f149单片机串口C程序
- 单片机延时C语言程序
- 基于单片机的红外发射C语言程序单片机
- javascript踩过的坑
- 深入理解javascript原型和闭包(13)-【作用域】和【上下文环境】
- 关于Python CGI编程前后端数据传递问题
- HttpSessionListener和HttpSessionBindingListener解析
- JavaScript搜索关键字返回结果关键字加红
- SN单片机c程序优化方法
- 蓝牙概述+nrf51822串口数据透传的程序
- JavaScript基础之JQuery与DOM
- 安卓拉窗帘效果
- MySQL:错误代码1215 无法添加外键约束的解决思路
- 数据结构java实现
- Mybatis高级查询(一)
- JavaScript: switch用法及注意事项
- Android 设计模式