我可以在C编程中使用乘法和除法移位吗?

时间:2009-02-04 09:40:43

标签: c bit-shift

是否可以使用>><<向左和向右移动,而不是使用*/进行转换?

对于8位:0x01 * 2 = 0000 | 0010。

9 个答案:

答案 0 :(得分:17)

当然(对于整数数学)你可以使用左乘两个乘以左移,并且右移乘二乘。

你不应该这样做。

有完美的左移和右移操作员,他们“完全按照他们对锡的说法”。为什么要混淆你的编译器或其他读取代码的人呢?

答案 1 :(得分:9)

你可以,但你为什么要这样做?转换操作是CPU可以做得最快的事情之一。

实际上,相反的情况经常被建议作为性能优化:使用移位来实现2次方的乘法/除法。

但是任何一个不太合适的编译器都会为你做到这一点,所以你绝对不应该手动执行:保持代码清晰是最重要的事情,所以如果你正在进行数学运算,请使用乘法和除法,并使用位移如果你在操纵比特。

答案 2 :(得分:8)

除非进行位操作,否则应避免在所有情况下进行移位。写作&lt;&lt;而不是* 2使代码不太清晰。除非你明确想要,否则不要使用位移。

编译器无论如何都会将*2 n 优化为<<

答案 3 :(得分:5)

你可以,但是将它优化为实际位移是一个聪明的编译器!另外,如果你的意思是“转移”,你最好写&lt;&lt;。当你的意思是'乘法'时,写下*。

请注意,浮点数根本不会改变:它们的指数只会增长。

答案 4 :(得分:3)

是的,除了一个问题:在处理负数时,除法可能以不同的方式正确转移。负数的右移行为是编译器定义的。

您当然可以使用无符号整数来避免此问题。

正如其他人所说,无论你使用移位还是乘法/除法,现代编译器都可能产生相同的输出。因此,使用任何使代码更容易遵循和维护的东西。

答案 5 :(得分:1)

是的,你可以。举个例子:

int main() {
  if ((1*2) == (1 << 1)) printf("you certainly can!\n");
  else printf("doesn't work that way\n");
}

它产生的输出:

you certainly can!

请参阅此回复的评论,了解为什么我们同意(0x01 * 2 == 0000 | 0010)比((1 * 2)==(1&lt;&lt; 1))更多问题,更简洁的版本。

答案 6 :(得分:1)

你可以,

x << 1 == x * 2
x << 2 == x * 4
etc...

and conversly

x >> 1 == x / 2
x >> 2 == x / 4
etc...

虽然我认为有经验的c程序员应该能够看到一点点转换操作,并且知道这两种方法是类似的。鉴于选择,我总是会使用位移,因为很清楚你的意图是什么。如果你确实使用了乘法/或除法选项,你显然需要评论为什么你突然将值乘以看似随机的数字。然而,位移明确表明您正在尝试移位。

至于任何optamization评论,除非绝对必要,例如时间关键的emebedded编程,我不会过分担心你的代码的optamization。代码可读性和可维护性应该是您的重点,而不是optamization!如果在开发结束时,您需要更多的性能,您可以随时返回并进行optamization(确保您非常谨慎地记录您所做的一切!)。但在开发过程中,我会选择最容易阅读和维护的内容,例如:使用'&lt;&lt;&lt; /'&gt;&gt;'。

答案 7 :(得分:0)

所有其他人都表示完全有可能这样做。这也毫无意义。如果你的意思是转移然后转移。如果你的意思是乘以然后乘以。不要将代码的读者与无用的“优化”混淆。

除问题外:

您的编译器将查看任何整数乘法/除以常量,并将表达式几乎一直减少到一系列移位/加法运算。这样做是因为二进制乘法并不是一项容易的任务,并且它比移位和加法需要更长的时间,一旦它们传入ALU,就可以在一个单一的时钟周期内完成。有趣的是CPU中的整数乘数大致相似但是以自动方式 - 使用单独的移位/添加操作仍然稍微快一些,因为您不需要停止并测试您正在进行的每个级别的转换的条件。

我可以为你起草这个基本算法,但它已经快到午夜所以你可以谷歌了。如果有足够的电话,我会编辑帖子并明天把它放进去。

这种优化尤其适用于乘以2 ^ n变量的常数,因为它是单个移位操作。

答案 8 :(得分:0)

是的你总能用2次乘法的力量代替换档,但正如已经指出的那样,为什么呢?没有指出的是,用移位替换乘法有时是有用的,而不仅仅是2的简单幂。例如,在320 * 200像素缓冲区的好日子里,像素字节的偏移是y * 320 + X。这可以按如下方式完成:

int OffsetXY( int x, int y)
{
    int offset;

    y <<= 6;
    offset = y;
    offset += y << 2;  // offset = original y * 320
    return offset + x;
}

虽然现在大多数开发人员只是学术兴趣,但它在嵌入式世界中很有用(最近在DS上做了一些编码,这种事情很有用)。