30

我正在研究 C# 中的移位运算符,试图找出何时在我的代码中使用它们。

我找到了答案,但对于 Java,您可以:

a) 进行更快的整数乘除运算:

*4839534 * 4* 可以这样完成: 4839534 << 2

或者

543894 / 2可以这样完成:543894 >> 1

对于大多数处理器来说,移位操作比乘法快得多。

b) 将字节流重组为 int 值

c) 用于加速图形操作,因为红色、绿色和蓝色由单独的字节编码。

d) 将小数字打包成一个长...


对于 b、c 和 d,我无法想象这里有一个真实的样本。

有谁知道我们是否可以在 C# 中完成所有这些项目?C#中的移位运算符有更多实际用途吗?

4

4 回答 4

38

无需将它们用于优化目的,因为编译器会为您处理这些。

仅在代码的真正意图是移位时才使用它们(如您问题中的其余示例所示)。其余时间只使用乘法和除法,以便代码的读者一眼就能理解。

于 2009-12-19T17:44:47.943 回答
17

除非有非常令人信服的理由,否则我的观点是,使用像这样的巧妙技巧通常只会使代码更加混乱,几乎没有附加价值。编译器编写者是一群聪明的开发人员,并且比普通程序员更了解这些技巧。例如,使用移位运算符将整数除以 2 的幂比除法更快,但这可能不是必需的,因为编译器会为您执行此操作。您可以通过查看 Microsoft C/C++ 编译器和 gcc 执行这些优化的程序集来了解这一点。

于 2009-12-19T17:49:59.217 回答
15

I will share an interesting use I've stumbled across in the past. This example is shamelessly copied from a supplemental answer to the question, "What does the [Flags] Enum Attribute mean in C#?"

[Flags]
public enum MyEnum
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3
}

This can be easier to expand upon than writing literal 1, 2, 4, 8, ... values, especially once you get past 17 flags.

The tradeoff is, if you need more than 31 flags (1 << 30), you also need to be careful to specify your enum as something with a higher upper bound than a signed integer (by declaring it as public enum MyEnum : ulong, for example, which will give you up to 64 flags). This is because...

1 << 29 == 536870912
1 << 30 == 1073741824
1 << 31 == -2147483648
1 << 32 == 1
1 << 33 == 2

By contrast, if you set an enum value directly to 2147483648, the compiler will throw an error.

As pointed out by ClickRick, even if your enum derives from ulong, your bit shift operation has to be performed against a ulong or your enum values will still be broken.

[Flags]
public enum MyEnum : ulong
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3,

    // Compiler error:
    // Constant value '-2147483648' cannot be converted to a 'ulong'
    // (Note this wouldn't be thrown if MyEnum derived from long)
    ThirtySecond = 1 << 31,

    // so what you would have to do instead is...
    ThirtySecond = 1UL << 31,
    ThirtyThird  = 1UL << 32,
    ThirtyFourth = 1UL << 33
}
于 2014-06-03T20:49:08.303 回答
6

查看有关二进制数系统算术移位的这些 Wikipedia 文章。我想他们会回答你的问题。

在当今的业务应用程序中很少遇到移位运算符。它们经常出现在与硬件交互或操作打包数据的低级代码中。它们在 64k 内存段的时代更为常见。

于 2009-12-19T17:43:48.763 回答