刚刚开始工做就被前辈训得一塌糊涂,特别是对于优化这一块没有一点潜意思,如今不得不从新学习代码优化。编程
对于优化C代码有不少有效的指导方针,可是对于完全地了解编译器和你工做的机器依然没法取代,一般,加快程序的速度也会加大代码量。这些增长的代码也会影响一个程序的复杂度和可读性,这是不可接受的,好比你在一些小型的设备上编程,例如:移动设备、PDA……,这些有着严格的内存限制,因而,在优化的座右铭是:写代码在内存和速度都应该优化。数组
整型数 / Integers
在咱们知道使用的数不多是负数的时候,应该使用unsigned int取代int,一些处理器处理整数算数运算的时候unsigned int比int快,因而,在一个紧致的循环里面定义一个整型变量,最好这样写代码:函数
register unsigned int variable_name;
然而,咱们不能保证编译器会注意到那个register关键字,也有可能,对某种处理器来讲,有没有unsigned是同样的。这两个关键字并非能够在全部的编译器中应用。记住,整形数运算要比浮点数运算快得多,由于处理器能够直接进行整型数运算,浮点数运算须要依赖于外部的浮点数处理器或者浮点数数学库。咱们处理小数的时候要精确点些(好比咱们在作一个简单的统计程序时),要限制结果不能超过100,要尽量晚的把它转化成浮点数。学习
除法和余数 / Division and Remainder
在标准的处理器中,根据分子和分母的不一样,一个32位的除法须要20-140个时钟周期来执行完成,等于一个固定的时间加上每一个位被除的时间。优化
Time (分子/ 分母) = C0 + C1* log2 (分子/分母)
= C0 + C1 * (log2 (分子) - log2 (分母)).
如今的ARM处理器须要消耗20+4.3N个时钟周期,这是一个很是费时的操做,要尽量的避免。在有些状况下,除法表达式能够用乘法表达是来重写。比方说,(a/b)>c能够写成a>(cb),条件是咱们已经知道b为非负数并且bc不会超过整型数的取值范围。若是咱们可以肯定其中的一个操做数为unsigned,那么使用无符号除法将会更好,由于它要比有符号除法快得多。ui
合并除法运算和取余运算 / Combining division and remainder
在一些状况下,除法运算和取余运算都须要用到,在这种状况下,编译器会将除法运算和取余运算合并,由于除法运算老是同时返回商和余数。若是两个运算都要用到,咱们能够将他们写到一块儿spa
int func_div_and_mod (int a, int b) {
return (a / b) + (a % b);
}
除数是2的幂的除法和取余 / Division and remainder by powers of two
若是除法运算中的除数是2的幂,咱们对这个除法运算还能够进一步优化,编译器会使用移位运算来进行这种除法运算。因此,咱们要尽量调整比例为2的幂(比方说要用64而不用66)。若是是无符号数,它要比有符号的除法快得多。code
typedef unsigned int uint;
uint div32u (uint a) {
return a / 32;
}
int div32s (int a) {
return a / 32;
}
这两种除法都会避免调用除法函数,另外,无符号的除法要比有符号的除法使用更少的指令。有符号的除法要耗费更多的时间,由于这种除法是使最终结果趋向于零的,而移位则是趋向于负无穷。索引
取模运算的替换 / An alternative for modulo arithmetic
咱们通常使用取余运算进行取模,不过,有时候使用 if 语句来重写也是可行的。考虑下面的两个例子:内存
uint modulo_func1 (uint count)
{
return (++count % 60);
}
uint modulo_func2 (uint count)
{
if (++count >= 60)
count = 0;
return (count);
}
第二个例子要比第一个更可取,由于由它产生的代码会更快,注意:这只是在count取值范围在0 – 59之间的时候才行。
可是咱们可使用以下的代码(笔者补充)实现等价的功能:
uint modulo_func3 (uint count)
{
if (++count >= 60)
count %= 60;
return (count);
}
使用数组索引 / Using array indices
假设你要依据某个变量的值,设置另外一个变量的取值为特定的字符,你可能会这样作:
switch(queue) {
case 0 : letter = 'W';
break;
case 1 : letter = 'S';
break;
case 2 : letter = 'U';
break;
}
或者这样:
if(queue == 0)
letter = 'W';
else if ( queue == 1 )
letter = 'S';
else
letter = 'U';
有一个简洁且快速的方式是简单的将变量的取值作成一个字符串索引,例如:
static char *classes = "WSU";
letter = classes[queue];
数据优化暂时先写这么多,请持续关注更新,更多干货和资料请直接联系我,也能够加群710520381,邀请码:柳猫,欢迎你们共同讨论