对于无符号和补码乘法来说,乘法运算的位级表示都是一样的。这表明机器可以用一种乘法指令来进行有符号和无符号整数的乘法。
在大多数机器上,整数乘法指令相当慢,需要 10 个或者更多的时钟周期,然而其他整数运算(例如加法、减法、位级运算和移位)只需要 1 个时钟周期。因此,编译器使用了一项重要的优化,试着用移位和加法和减法运算的组合来代替乘以常数因子的乘法。
对于一个任务,对于某个常数 K 的表达式 x * K 生成代码。编译器会将 K 的二进制表示吧表达为一组 0 和 1 交替的序列:
[(0...0)(1...1)(0...0)...(1...1)]
考虑一组从位位置 n 到位位置 m 的连续的 1(n >= m)。可以只用下面两种不同形式中的一种来计算这些位对乘积的影响:
形式A:(x << n) + (x << n - 1) + ... + (x << m)
形式B:(x << n + 1) - (x << m)
把每个这样连续的 1 的结果加起来,不用做乘法,就能计算出 x * K。当然,选择使用移位、加法和减法的组合,还是使用一条乘法指令,取决于这些指令的相对速度,而这些是与机器高度相关的。大多数编译器只在需要少量移位、加法和减法就足够的时候才使用这种优化。
对于位位置 n 为最高有效位的情况,B表达式简单地变成了-(x << m)。要看清这一点,设字长为w, n = w - 1.形式B说要计算(x << w) - (x << m),但是将 x 向做移动 w 位会得到值 0。