当前位置: 首页 > 科技观察

一些C语言程序员说,用移位运算代替乘除运算效率更高,是真的吗?

时间:2023-03-13 05:01:40 科技观察

在C语言程序开发中,有些移位运算似乎可以达到与乘除运算相同的效果。例如4>>1等于2,右移一位相当于除以2。同理,2<<1等于4,左移一位相当于乘以2。因此,有些教科书推荐用移位运算代替乘除运算,声称这样可以提高最终C语言程序的运行效率,这是真的吗?移位代替乘除法,C语言程序效率更高吗?答案是最好的简单直接的方法就是做实验。这里有两个关于散列算法的C语言程序。请看:unsignedinthash(charconst*s){unsignedh=0;while(*s!='\0'){h=127*h+(unsignedchar)*s;++s;}returnh;}读者要重点关注h=127*h+(unsignedchar)*s;这一行,此时C语言代码使用了乘法运算。下面是另外一段C语言代码,请看:unsignedinthash(charconst*s){unsignedh=0;while(*s!='\0'){h=(h<<7)-h+(unsignedchar)*;++s;}returnh;}唯一的区别是使用了h<<7的移位运算,而不是127*h的乘法运算。与前面的C语言代码相比,唯一的区别就是用了h<<7的移位运算,而不是127*h的乘法运算。在我的机器上测试了这两段C语言代码的效率,结果是两者速度差不多,而且有时127*h版本的C语言代码更快!在解析C语言程序时,用移位运算代替乘除运算是不是更快?现在我们有了这个问题的答案:不是真的。原因是C语言编译器一般会优化我们的代码。它知道如何尽快增加目标处理器架构的能力,即尽可能快地生成程序。因此,作为C语言程序员,我们应该做的是明确告诉编译器我们的意图(即是i*2还是i<<1),让它根据上下文决定如何生成更快的指令。当硬件不支持快速乘法和除法时,编译器将乘法和除法转换为适当的移位和加法/减法组合。因为它知道我们的最终目的,所以有时候直接告诉编译器我们的目的,显式地写出移位代码会更好,这样可以得到尽可能最快的C语言程序。事实上,有时简单的移位运算并不等同于乘除法,有些乘法不能通过简单的移位来实现,例如:-5/2=-2-5>>1=-3i*3=(i<<1)+ii*10=(i<<3)+(i<<1)因此,用移位运算代替乘除运算可能会带来意想不到的结果。而且一些shift组合会让同事很难理解这段C语言代码的真实意图,不利于协同开发和后期维护。小结本节讨论C语言程序开发中移位运算和乘除运算的关系,并讨论它们之间的效率问题。可见,我们无需纠结于两者的取舍。事实上,考虑到代码的可读性和编译器的优化特性,我们应该写“有意”的代码,即在我们要实现乘除运算的时候写乘除代码。当你想实现一个移位操作时,编写移位代码。