先简单小结一下:
当编译器优化能力很弱时,用移位代替简单除法(除2,4,8,16...)效率更高;
当编译器优化能力很弱时,在低端CPU上,用移位代替简单乘法(乘2,4,8,16...)效率更高
其它情况下,在C语言程序中,用移位操作代替乘除运算没什么效果,反而降低了代码的可读性
下面简单说一下各种情况:
编译器因素
现代C编译器对于简单的2,4,8之类的乘除法,会在优化时根据条件自动转换成移位运算。这时,没有必要手动使用移位操作符代替乘除,相信编译器的优化能力就好了。有时候为了更好的适配目标CPU,可以给编译器提供详细参数,如ARMC编译器可指定乘法指令所需周期数,这就方便编译器针对特定CPU进行优化。
除法
当编译器不能进行自动移位优化时,对于简单除法,使用移位操作代替会有一定效果:由于除法的算法特性,RISCCPU(如ARM系列绝大多数CPU)都没有完整的整数除法指令,这是基于除法特殊性造成的。如果用浮点数除法模拟,则结果未必正确,同时起码需要十几个时钟周期才能完成。这时,如果能用两三次移位操作和加法组合完成除法,当然会有效率的提高。
再说说CPU的影响:
低端CPU
这里提到的低端CPU,指的是没有硬件乘法器、也没有浮点协处理器的CPU。这类CPU的乘法需要用加法模拟,因此速度较慢。此时,用移位操作代替简单的乘法能提高效率。
低端CPU举例:无MAC单元的ARMCortex-M系列CPU,AVR的Atmega等各8位MCU。
中高端CPU
中高端CPU通常都有乘法器和浮点协处理器。对于这类CPU,用移位代替乘法意义不大,也许能在CPU指令发射时降低流水线阻塞(这是由于多发射高端CPU的移位处理单元数量多于乘法器数量),从而提高微量的性能,但总体影响微乎其微。