HEW中有效的编程技术--笔记
来源:互联网 发布:json对象解析不出来 编辑:程序博客网 时间:2024/05/16 05:46
有效的编程技术
1.为增进 ROM 的效率和执行速度,可用 1 字节大小来代表的数据,应被声明为字符/无符号字符 (char/unsigned char) 类型。
2.为增进目标的效率和执行速度,任何具有正数值的变量应被声明为无符号。
3.禁止冗余类型转换、通过确保在相同大小的数据项目之间执行操作,可增进 ROM 的效率和执行速度。
4.使用 const 限定符、保持值不变的初始化数据应被列为常数以节省 RAM 区域。
已初始化的数据项目经常可能在值上变更。 这些数据项目于连接期间在 ROM 上分配,并在程序执行开始时被复制到 RAM,导致它们同时在 ROM 和 RAM 区域内被分配。 在程序执行的过程中保持值不变的数据项目可被列为常数,以使它们只在 ROM区域内被分配。
Eg: unsigned char a[5]={1, 2, 3, 4, 5};
const unsigned char a[5]={1, 2, 3, 4, 5};//优化后
在优化前,除了 ROM 以外,程序还需要在 RAM 为分配目标大小表中所列出的数据区域大小。
5.使用一致的变量大小,在循环语句中作比较时,可使用统一的变量大小来消除对扩展代码的需要,并缩减所产生的代码大小。
6.将 in-file 函数指定为静态函数,只在一个文件中使用的函数应被指定为静态 (static)。指定为静态的函数若不被外部函数所调用,则将被删除。当为内联扩展指定时,这些函数也将被删除,以增进大小效率。
7.统一公用表达式,通过在多个算术表达式中统一公用组件,可增进 ROM 的效率和执行速度。
Eg:(优化前的 C 语言程序)
unsigned char a,b,w,x,y,z;
void func(void)
{
a=x+y+z;
b=x+y+w;
}
(优化后的 C 语言程序)
unsigned char a,b,w,x,y,z;
void func(void)
{
unsigned char tmp;
tmp=x+y;
a=tmp+z;
b=tmp+w;
}
8.增进条件决定, 通过评估一次操作中的相似条件表达式来增进 ROM 的效率。
(优化前的 C 语言程序)
unsigned char a,b;
unsigned char func(void)
{
if (!a) return(0);
if (a&&!b) return(0);
return(1);
}
(优化后的 C 语言程序)
unsigned char a,b;
unsigned char func(void)
{
if (a&&b) return(1);
else return(0);
}
9.使用替换值的条件决定
当在条件表达式中对决定语句使用替换值时,可通过将赋值语句视为条件决定语句来增进 ROM 的效率。
(优化前的 C 语言程序)
char *s,*d;
void func(void)
{
while(*s){
*d++ = *s++;
}
*d++ = *s++;
}
(优化后的 C 语言程序)
char *s,*d;
void func(void)
{
while(*d++ = *s++);
}
10.使用合适的运算法
如果算术表达式包含常用术语,应将这些术语析出以缩减执行算术操作的次数。 这可同时增进 ROM 的效率和执行速度。
解决三阶方程式。
(优化前的 C 语言程序)
unsigned char a,b,c,d,x,y;
void func(void)
{
y=a*x*x*x+b*x*x+c*x+d;
}
(优化后的 C 语言程序)
unsigned char a,b,c,d,x,y;
void func(void)
{
y=x*(x*(a*x+b)+c)+d;
}
11.使用公式
使用数学公式以缩减面向算法的编码技术中所需的算术操作次数。 这可同时增进 ROM 的效率和执行速度。
计算 1 到 100 的总和。
(优化前的 C 语言程序)
unsigned int s;
unsigned int n=100;
void func(void)
{
unsigned int i;
for (s=0,i=1;i<=n;i++)
s+=i;
}
(优化后的 C 语言程序)
unsigned int s;
unsigned int n=100;
void func(void)
{
s=n*(n+1)>>1;
}
12.使用本地变量
通过将可用作本地变量的临时变量、循环计数器等声明为本地变量,可增进 ROM 的效率和执行速度。
同样地,在对本地变量执行操作前,可通过将多个算术表达式的普遍外部变量分配给本地变量来提高效率。
将变量 a 增加到变量 b、c 和 d;将结果存储在变量 b、c 和 d 内。
(优化前的 C 语言程序)
unsigned char a,b,c,d;
void func(void)
{
b+=a;
c+=a;
d+=a;
}
(优化后的 C 语言程序)
unsigned char a,b,c,d;
void func(void)
{
unsigned char wk;
wk=a;
b+=wk;
c+=wk;
d+=wk;
}
13.将 f 分配给浮点类型常数
在浮点算术操作涉及包含在浮点类型的可分配值范围内(7.0064923216240862e-46f 到 3.4028235677973364e+38f)的常数的情形下,在数字值之后分配字母“f”以消除可能转换为复式 (double) 类型的冗余类型转换。
(优化前的 C 语言程序)
float a,b;
void func(void)
{
a=b+1.0;
}
(优化后的 C 语言程序)
float a,b;
void func(void)
{
a=b+1.0f;
}
14.指定移位操作中的常数
对于移位操作,如果移位计数是一个变量,编译程序将会调用运行时例程以处理操作。 如果移位计数是一个常数,编译程序将不会调用可有效增进执行速度的运行时例程。
(优化前的 C 语言程序)
int data;
int sht=8;
void func(void)
{
data=data<<sht;
}
(优化后的 C 语言程序)
#define SHT 8
int data;
void func(void)
{
data=data<<SHT;
}
15.使用移位操作
在进行乘法和加法运算时,尽可能使用移位操作。
(优化前的 C 语言程序)
int data,a;
void main()
{
a=data+data+data;
}
(优化后的 C 语言程序)
int data,a;
void main()
{
a=(data<<1)+data;
}
16.统一连续 ADD 指令
在遇到连续加法代码时,编译程序将执行一致的优化。 要充分利用此优化,必须尽可能地将加法运算连续编码。
(优化前的 C 语言程序)
int a,b;
void main()
{
a+=10;
b=10;
a+=20;
}
(优化后的 C 语言程序)
int a,b;
void main()
{
b=10;
a+=10;
a+=20;
}
17.循环处理
通过使用减量计数器及将终止条件和零相比,可增进 ROM 的效率和执行速度。
(优化前的 C 语言程序)
unsigned char a[10],b[10];
int i;
void func(void)
{
for(i=0; i<10; i++)
b[i]=a[i];
}
(优化后的 C 语言程序)
unsigned char a[10],b[10];
int i;
void func(void)
{
for(i=9; i>=0; i--)
b[i]=a[i];
}
18.选择重复控制语句
如果循环语句被执行至少一次,应该使用 do-while 语句来将它编码以缩减循环计数决定的一次操作,从而增进 ROM 的效率和执行速度。
(优化前的 C 语言程序)
unsigned char a[10],len=10;
unsigned char p1[10],p2[10];
void func(void)
{
char i;
for (i=len; i>0; i--)
p1[i-1]=p2[i-1];
}
(优化后的 C 语言程序)
unsigned char a[10],len=10;
unsigned char p1[10],p2[10];
void func(void)
{
char i=len;
do{
p1[i-1]=p2[i-1];
} while(--i);
}
19.将不变量表达式从循环的内部移到外部
如果出现在循环内部的不等在循环外部被定义,不等只在循环的开头被评估,这将缩减在循环中执行的指令数目。 结果执行速度获得增进
(优化前的 C 语言程序)
unsigned char a[10],b,c;
int i;
void func(void)
{
for (i=9; i>=0; i--)
a[i]=b+c;
}
(优化后的 C 语言程序)
unsigned char a[10],b,c;
int i;
void func(void)
{
unsigned char tmp;
tmp=b+c;
for (i=9; i>=0; i--)
a[i]=tmp;
}
20.合并循环条件
在循环条件相同或相似的情形下,可通过将它们合并来增进 ROM 的效率和执行速度。
(优化前的 C 语言程序)
int a[10],b[10];
void f(void)
{
int i,j;
for (i=0; i<10; i++)
a[i]=0;
for (j=0; j<10; j++)
b[j]=1;
}
(优化后的 C 语言程序)
int a[10],b[10];
void f(void)
{
int i;
for (i=0; i<10; i++){
a[i]=0;
b[i]=1;
}
}
21.使用指针变量
如相同变量(外部变量)被屡次参考或必须存取数组元素,ROM 的效率和执行速度可通过使用指针变量来增进。
使用指针变量会生成采用有效率的寻址模式(@Rn、@Rn+、@-Rn)的代码。
实例
将数组 data2 的元素复制到数组 data1。
(优化前的 C 语言程序)
void func(int data1[],int data2[])
{
int i;
for (i=0; i<10; i++)
data1[i]=data2[i];
}
(优化后的 C 语言程序)
void func(int *data1,int *data2)
{
int i;
for (i=0; i<10; i++){
*data1=*data2;
data1++; data2++;
}
}
22.确保数据兼容性
数据项目以所声明的顺序分配。 通过有效指定数据项目声明的顺序以消除虚设存储区的生成,可增进使用 ROM 和 RAM 的效率。
实例
分配总数 8 字节的数据。
(优化前的 C 语言程序)
char a;
long b;
char c;
short d;
(优化后的 C 语言程序)
char a;
char c;
long b;
short d;
23.数据初始化的技术
要缩减程序大小,任何需要初始化的变量必须在声明时被初始化。
24.统一数组元素的初始化
在一些数组元素必须被初始化的情况下,通过将它们分组到结构以使它们可以在单一操作中被初始化,将可增进 ROM 的效率。
使用相应值对化数组 a、b 和 c 进行初始化。
(优化前的 C 语言程序)
void f(void)
{
unsigned char a[]={0,1,2,3};
unsigned char b[]="abcdefg";
unsigned char c[]="ABCDEFG";
}
(优化后的 C 语言程序)
void f(void)
{
struct x{
unsigned char a[4];
unsigned char b[8];
unsigned char c[7];
} A
={0,1,2,3,"abcdefg","ABCDEFG"};
}
25.将参数传递为结构地址
未被分配到寄存器的参数必须使用结构的地址来传递以缩减程序大小。
在需要大的参数和使用大量参数的情况下,必须在将参数传递到目标函数之前,将它们在结构中分组以缩减程序大小。 如果参数被声明为结构的成员,且结构的起始地址被当作参数传递到目标函数,接收函数将可依据接收地址来存取成员。
实例
将长类型数据 a、b、c 和 d 传递到函数 func。
(优化前的 C 语言程序)
void sub(long,long,long,long);
long a,b,c,d;
void func(void)
{
sub(a,b,c,d);
}
(优化后的 C 语言程序)
void sub(struct ctag *);
struct ctag{
long a;
long b;
long c;
long d;
}x;
void func(void)
{
sub(&x);
}
26.将结构分配给寄存器
在本地变量被当作结构使用时,必须声明成员以便可以将变量直接分配到寄存器。
实例
将结构数据传递到函数 func。
(优化前的 C 语言程序)
struct ST {
char a;
short b;
char c;
}pst;
void main()
{
struct ST s;
s.a=pst.a+10;
s.b=s.a+s.c;
func(s);
}
(优化后的 C 语言程序)
struct ST {
short b;
char a;
char c;
}pst;
void main()
{
struct ST s;
s.a=pst.a+10;
s.b=s.a+s.c;
func(s);
}
27.增进函数被定义的程序位置
通过在同一文件中定义任何经常在模块中调用的函数,可能可以增进 ROM 的效率和执行速度。
实例
从函数 func 和 func1 调用函数 func2。
(优化前的 C 语言程序)
extern int func2(void);
int ret;
void func(void)
{
int i;
i=func2();
ret = i;
}
void func1(void)
{
int i;
i=func2();
ret = i;
}
(优化后的 C 语言程序)
int ret;
int func2(void)
{
return 0;
}
void func(void)
{
int i;
i=func2();
ret = i;
}
void func1(void)
{
int i;
i=func2();
}
28.宏调用
在相同处理例程被定义为宏时,它们将会在被调用的位置进行内联扩展。 这将消除代码的生成和增进效率。
实例
调用函数 abs。
(优化前的 C 语言程序)
extern int a,b,c;
int abs(x)
int x;
{ return x>=0?x:-x; }
void f(void)
{
a=abs(b);
b=abs(c);
}
(优化后的 C 语言程序)
#define abs(x) ((x)>=0?(x):-(x))
extern int a,b,c;
void f(void)
{
a=abs(b);
b=abs(c);
}
29.声明原型
具有字符类型或无符号字符类型参数的函数,必须在被调用之前进行原型声明以消除冗余类型转换代码的输出。
实例
调用具有字符类型或无符号字符类型参数的函数 sub1。
(优化前的 C 语言程序)
char a;
unsigned char b;
void func(void)
{
sub1(a,b);
}
(优化后的 C 语言程序)
void sub1(char, unsigned char);
char a;
unsigned char b;
void func(void)
{
sub1(a,b);
}
30.尾递归的优化
如果函数进行了一个函数调用,观察函数调用是否可以移动到调用源函数的尾端。 这可同时增进 ROM 的效率和执行速度。
尾递归优化会在满足以下所有条件后执行:
调用源函数不会在堆栈上放置它的参数或返回值地址。
该函数调用之后即是 RTS 指令。
实例
调用函数 sub 并更新外部变量的值。
(优化前的 C 语言程序)
void g(void);
int a;
void main(void)
{
if (a==0) a++;
else{
g();
a+=2;
}
}
(优化后的 C 语言程序)
void g(void);
int a;
void main(void)
{
if (a==0) a++;
else{
a+=2;
g();
}
}
31.增进参数传递的方式
要缩减代码大小,必须调整参数列出时的顺序以使参数之间没有间隙。
(优化前的 C 语言程序)
long rtn;
void func(char,short,char);
void main()
{
short a;
char b,c;
func(b,a,c);
}
void func(char x,short y,char z)
{
rtn=x*y+z;
}
(优化后的 C 语言程序)
long rtn;
void func(char,char,short);
void main()
{
short a;
char b,c;
func(b,c,a);
}
void func(char x,char y,short z)
{
rtn=x*y+z;
}
32.将切换语句重写为表
如果case 语句所执行的与switch 关联的处理任务是相似的,switch 语句必须使用一个表来编码以缩减目标大小。
实例
根据函数 a 的值转移到一个函数。
(优化前的 C 语言程序)
extern void f1(void);
extern void f2(void);
extern void f3(void);
extern void f4(void);
extern void f5(void);
extern int a;
void sub(void)
{
switch(a){
case 0:f1();break;
case 1:f2();break;
case 2:f3();break;
case 3:f4();break;
case 4:f5();break;
}
}
(优化后的 C 语言程序)
extern void f1(void);
extern void f2(void);
extern void f3(void);
extern void f4(void);
extern void f5(void);
extern int a;
void sub(void)
{
static int (*key[5])()=
{f1,f2,f3,f4,f5};
(*key[a])();
}
33.编写 Case 语句跳转至相同标签的程序
包含相同表达式的 case 语句必须组合在一起,以减少转移指令的数目并缩减目标大小。
(优化前的 C 语言程序)
long ll;
void func(void)
{
char c;
switch(c){
case 0: ll=0; break;
case 1: ll=0; break;
case 2: ll=1; break;
case 3: ll=1; break;
case 4: ll=2; break;
}
}
(优化后的 C 语言程序)
long ll;
void func(void)
{
char c;
switch(c){
case 0:
case 1: ll=0; break;
case 2:
case 3: ll=1; break;
case 4: ll=2; break;
}
}
34.转移到直接在指定语句下编码的函数
如果函数调用出现在函数的尾端,必须将调用目标函数直接放置在函数调用下面。
如果尾递归优化正在进行,必须将调用目标函数直接放置在函数调用下面,以充分利用此优化来产生删除函数调用代码的效果。由于删除了函数调用代码,程序的大小将会缩减而处理速度将会增加。
实例
从函数 main 调用函数 func。
(优化前的 C 语言程序)
int a;
void func();
void func()
{
a++;
}
void main()
{
a=0;
func();
}
(优化后的 C 语言程序)
int a;
void func();
void main()
{
a=0;
func();
}
void func()
{
a++;
}
- HEW中有效的编程技术--笔记
- HEW中RX62N工程自动生成文件的解析
- HEW中RX62N工程自动生成文件的解析
- 如何有效的提高自己的编程技术?
- HEW中文注释 设定缺省的工程路径
- 项目控制的有效技术
- [Eclipse笔记]在SWT中有效的管理图形系统资源
- 怎样有效的学习编程
- 极限编程的有效实践
- 网路编程技术笔记
- 网络编程技术笔记
- 《More Effective C++ 35个改善编程与设计的有效方法》——第一章笔记
- 论有效的需求变更技术
- 有效测试软件的方法与技术
- 有效的XML文档以及解析技术
- SDK编程中有效区域与无效区域的盲区WM_PAINT消息何时发送的。。。
- 有效编程的75条军规
- 有效编程的14件事
- ORACLE存大文件出现 错误:读取违反顺序
- 世界名人眼中的“熊猫烧香”
- OSWorkflow入门学习4--包用途分析及代码片断
- Getting Started 系列 - Netbeans 的 Action
- C#中Windows通用的回车转Tab方法
- HEW中有效的编程技术--笔记
- NOKIA 6681 现在发不了短信 如何从装系统?
- NetBeans Splash Screen 加入 Login Dialog
- 关于DestroyWindow()和PostQuitMessage()的少许疑问
- 练习题(3.28)
- 笑话之-猴子拣到ip卡
- 报到
- ExecuteNonQuery(),ExecuteReader()与ExecuteScalar()
- 3.28晴