超炫酷技巧!C语言代码优化的技巧( 四 )


在正常情况下 , getchar的确返回单个字符 。但如果getchar碰到文件结束标志或发生读错误 , 它必须返回一个标志EOF 。为了区别于正常的字符 , 只好将EOF定义为负数(通常为负1) 。因此函数getchar就成了int类型 。
我们在实际工作中 , 经常会碰到上述令人为难的问题 。为了避免出现误解 , 我们应该将正常值和错误标志分开 。即:正常值用输出参数获得 , 而错误标志用return语句返回 。
函数getchar可以改写成BOOL GetChar(char*c); 。
7、附加返回值 , 增强函数的灵活性有时候函数原本不需要返回值 , 但为了增加灵活性如支持链式表达 , 可以附加返回值 。例如字符串拷贝函数strcpy的原型:
char *strcpy(char *strDest , const char *strSrc);strcpy函数将strSrc拷贝至输出参数strDest中 , 同时函数的返回值又是strDest 。这样做并非多此一举 , 可以获得如下灵活性:
char str[20];int length=strlen(strcpy(str,“HelloWorld”)); 
循环展开简单的循环可以展开以获取更好的性能 , 但需要付出代码体积增加的代价 。循环展开后 , 循环计数应该越来越小从而执行更少的代码分支 。
如果循环迭代次数只有几次 , 那么可以完全展开循环 , 以便消除循坏带来的负担 。例如:
for(i=0;i<3;i++){something(i);}展开为:
something(0);something(1);something(2);这可以非常可观的节省性能 , 原因是代码不用每次循环需要检查和增加i的值 。
if判断条件的顺序if的判断条件中概率最大的情况应放在前面 。例子:
if(1==condition){}elseif(2==condition){}else{}此处 , 若condition为1的概率大较大则把if (1 == condition)放在前面 。
若condition为2概率大较大则把if (2 == condition)放在前面 , 如:
if(2==condition){}elseif(1==condition){}else{}这里有个小细节:在用if判断某个变量与某个常量是否相等时 , 可以把常量写在前面变量写在后面 , 如:
if(2==condition)2放在前面 , condition放在后面 。这样的好处就是当你漏敲了一个=号时 , 编译器会指出你的这个错误 。
尽早退出循环通常 , 循环并不需要全部都执行 。例如 , 如果我们在从数组中查找一个特殊的值 , 一经找到 , 我们应该尽可能早的断开循环 。
例如:如下循环从10000个整数中查找是否存在-99 。
found=FALSE;for(i=0;i<10000;i++){if(list[i]==-99){found=TRUE;}}if(found){printf("Yes,thereisa-99.Hooray!n");}这段代码无论我们是否查找得到 , 循环都会全部执行完 。更好的方法是一旦找到我们查找的数字就终止继续查询 。
把程序修改为:
found=FALSE;for(i=0;i<10000;i++){if(list[i]==-99){found=TRUE;break;}}if(found){printf("Yes,thereisa-99.Hooray!n");}假如待查数据位于第23个位置上 , 程序便会执行23次 , 从而节省9977次循环 。
使用位运算替代四则运算在许多古老的微处理器上 ,  位运算比加减运算略快 ,  通常位运算比乘除法运算要快很多 。
在现代架构中 ,  位运算的运算速度通常与加法运算相同 , 但仍然快于乘法运算 。所以通常乘以或除以2n可以使用位运算来代替四则运算 , 如
a=a*8;a=a/8;a=a%8;修改为:
a=a<<3;a=a>>3;a=a&7;以空间换时间在内存比较充足的情况下 , 可以使用空间来换取时间 。比如使用查表法 , 把一些可能的结果事先保存到表中 。例如求阶乘通常的做法是:
longfactorial(inti){if(i==0)return1;elsereturni*factorial(i-1);}若是空间比较足 , 而且所需的结果都能列举出来 , 则代码可以修改为:
staticlongfactorial_table[]={1 , 1 , 2 , 6 , 24 , 120 , 720/*etc*/};longfactorial(inti){returnfactorial_table[i];}使用复合赋值语句增加一个变量的值有两种方式 , 如:a = a + 5和a += 5 。存在两种增加一个变量值的方法有何意义呢?
K&R C设计者认为复合赋值符可以让程序员把代码写得更清楚些 。另外 , 编译器可以产生更为紧凑的代码 。


推荐阅读