2

代替使用>><<移位,是否可以使用*/左右移位?

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

4

9 回答 9

17

您当然可以(对于整数数学)使用乘以 2 进行左移,并使用除以 2 进行右移。

你不应该这样做。

有非常好的左移和右移运算符,它们“完全按照他们所说的那样做”。为什么要让您的编译器或其他阅读您的代码的人感到困惑?

于 2009-02-04T09:45:52.487 回答
9

你可以,但你为什么要这样做?移位操作是 CPU 可以最快完成的事情之一。

实际上,通常建议相反作为性能优化:使用移位来实现 2 的幂的乘法/除法。

但是任何半体面的编译器都会为你做这件事,所以你绝对不应该手动做:保持你的代码清晰是最重要的,所以如果你在做数学,使用乘法和除法,如果你使用位移位'重新操作位。

于 2009-02-04T09:50:59.200 回答
8

除了进行位操作外,您应该避免在所有情况下进行移位。写 << 而不是 * 2 会使代码不那么易读。除非您明确需要,否则不要使用位移位。

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

于 2009-02-04T09:50:53.663 回答
5

您可以,但是将其优化为实际的位移位将是一个智能编译器!另外,如果你的意思是“转变”,你最好写 <<。当你的意思是“乘”时,写 *.

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

于 2009-02-04T09:43:29.247 回答
3

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

您当然可以通过使用无符号整数来避免这个问题。

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

于 2009-02-04T10:18:49.130 回答
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 << 1)) 更成问题,这是一个更简洁的版本。

于 2009-02-04T09:45:02.317 回答
1

你可以,

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

反过来

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

尽管我认为经验丰富的 c 程序员应该能够查看位移操作并知道这两种方法是相似的。考虑到选择,我总是会使用位移,因为很清楚你的意图是什么。如果您确实使用了乘法/或除法选项,您显然需要评论为什么突然将值乘以看似随机的数字。而位移清楚地记录了您正在尝试位移位。

至于任何优化注释,除非绝对必要,例如时间要求严格的嵌入式编程,否则我不会过分担心代码的优化。代码可读性和可维护性应该是您的重点,而不是优化!如果在开发结束时,您需要更高的性能,您可以随时返回并进行优化(确保您仔细记录您所做的一切!)。但是在开发过程中,我会选择最容易阅读和维护的东西,例如使用'<<' / '>>'。

于 2009-02-04T09:51:25.657 回答
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 上做了一些编码,这种东西很有用)。

于 2009-02-05T14:25:37.613 回答
0

所有其他人都说这是完全有可能做到的。这也是没有意义的。如果你的意思是转移,那么转移。如果你的意思是相乘,那就相乘。不要将代码的读者与无用的“优化”混淆。

除了问题:

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

我可以在这里为你起草基本算法,但现在快午夜了,所以你可以用谷歌搜索它。如果有足够的需求,我会编辑帖子并在明天发布。

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

于 2009-02-04T13:23:31.050 回答