本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第2章,建议14-4,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
建议14-4:尽量避免在同一个数据上执行位操作与算术运算
虽然位操作在很大程度上可以提高程序的执行效率,但在同一个变量上执行位操作和算术运算会模糊程序员的意图,削弱代码的可移植性与可读性,还会导致安全审核员或代码维护人员难以确定应该执行什么检查以消除安全缺陷,保证数据的完整性。示例代码如下:
unsigned int x=10;
x+=(x<<3)-5;
虽然上面的代码是一条合法的优化语句,但是它的确严重地破坏了程序的可读性。因此,建议采用下面的方式来书写代码:
unsigned int x=10;
x=x*9-5;
或许这时候有读者会问,这样写代码不就降低了程序的执行效率吗?
其实不然,有些优化编译器会比我们做得更好。以整数乘法为例,如果目标系统有乘法指令,硬件的乘法比自己用移位操作实现的乘法要快得多;如果目标系统没有乘法指令,编译器会自动用移位等操作来优化乘法,示例代码如下:
unsigned int x=8;
unsigned int y=x*4;
unsigned int z=x/2;
上面的代码在Microsoft Visual Studio 2010集成开发环境VC++的Debug模式下将生成如下汇编代码:
unsigned int x=8;
00DB139E mov dword ptr [x],8
unsigned int y=x*4;
00DB13A5 mov eax,dword ptr [x]
00DB13A8 shl eax,2
00DB13AB mov dword ptr [y],eax
unsigned int z=x/2;
00DB13AE mov eax,dword ptr [x]
00DB13B1 shr eax,1
00DB13B3 mov dword ptr [z],eax
从上面的汇编代码可以看出,编译器会自动在汇编代码中用移位操作来优化乘除法运算。因此,完全没有必要用手工进行这种优化,编译器会自动完成。我们应该把精力放在改进程序的算法上,一个好的算法可以使程序运行效率大大提高。当然,如果除数为2的幂,那么在进行除法运算时可以适当地采用移位算法来实现乘除法。
除此之外,采用移位操作还需要注意不要超过该数据类型的精度范围(数据范围),示例代码如下:
#include <stdio.h>
int main (void)
{
int x=-2147483647;
x=x<<1;
printf("%d \n",x);
return 0;
}
在上面的代码中就要注意精度问题,在32位系统中,int类型占4个字节,精度范围为“-2147483647~2147483647”。其中,数据“-2147483647”的原码为“11111111111111111111111111111111”,补码为“10000000000000000000000000000001”。现在将“10000000000000000000000000000001”左移1位,最高位的1没有了,最低位左移一位,得到的结果为2。