【问题标题】:Understand the shift operator了解移位运算符
【发布时间】:2010-10-02 09:54:34
【问题描述】:

这个移位运算符我看不懂(c#参考):

class MainClass1
{
 static void Main()
    {
        int i = 1;
        long lg = 1;
        Console.WriteLine("0x{0:x}", i << 1);
        Console.WriteLine("0x{0:x}", i << 33);
        Console.WriteLine("0x{0:x}", lg << 33);
    }
}

/*
Output:
0x2
0x2
0x200000000
*/

class MainClass2
{
     static void Main()
     {
         int a = 1000;
         a <<= 4;
         Console.WriteLine(a);
     }
}

/*
Output:
16000
*/

【问题讨论】:

    标签: c#


    【解决方案1】:

    &lt;&lt; 是左移运算符;这采用一个值的二进制表示,并将所有位“n”位向左移动(“mod”除外,参见“1”),用零回填。

    &gt;&gt; 是右移运算符;这几乎相反(向右移动),除了有符号值(即可以为负的值)之外,它用 1 回填负值,否则为零。

    1:

    移位运算符本质上是“修改”数据的宽度。 int 是 32 位,因此左移 33(在 Int32 中)与左移 1 完全相同。您不会得到全零。 long 是 64 位,因此左移 33 会给出不同的答案(原始时间为 2^33)。

    2:

    每个左移(在数据宽度内)与 x2 相同(对于整数) - 所以

    这是简单的二进制:

    0000000001 = 1
    

    0000000010 = 2
    

    0000000100 = 4
    

    0000001000 = 8
    

    【讨论】:

    • 嗨,我可以请你解释一下吗?在第一个为什么我有 0x200000000 而在第二个为什么我有 16000?非常感谢
    • 这就像在说“为什么 1 * 50000 与 1000 * 8 不同” - 因为您正在做非常不同的事情。第一个是 2^33(“幂”),第二个是 1000*16。
    • 好的,我了解 2^33 和 1000*16 之间的区别,我想知道为什么是 2^32
    • 33 是 int (2^ 5) 现在改为 long (2^ 6) 为什么是 2^33?谢谢
    • 1
    【解决方案2】:

    只是稍微扩展一下 Marc 的答案(Marc,请随意将其包含在您的答案中,我将删除此答案),这是在规范的第 7.8 节中指定的:


    下面列出了预定义的移位运算符。

    左移:

    • int 运算符
    • uint 运算符
    • 长运算符
    • ulong 运算符

    x的结果类型范围之外的高位被丢弃,剩余位左移,低位空位位置置零。

    右移:

    • int 运算符 >>(int x, int count);
    • uint 运算符 >>(uint x, int count);
    • 长运算符 >>(long x, int count);
    • ulong 运算符>>(ulong x, int count);

    >> 运算符将 x 右移一个位数,如下所述。

    当 x 为 int 或 long 类型时,x 的低位被丢弃,其余位右移,如果 x 为非负且设置为如果 x 为负数,则为一。

    当x为uint或ulong类型时,x的低位被丢弃,其余位右移,高位空位置零。

    对于预定义的运算符,要移位的位数计算如下:

    当 x 的类型为 int 或 uint 时,移位计数由 count 的低五位给出。换句话说,移位计数是从 count & 0x1F 计算出来的。

    当x的类型为long或ulong时,移位计数由count的低六位给出。换句话说,移位计数是从 count & 0x3F 计算出来的。

    如果结果移位计数为零,则移位运算符只返回 x 的值。


    【讨论】:

      【解决方案3】:

      给新手程序员的一些注意事项:

      为什么要使用移位运算符?他们似乎做的不多。嗯,有两个原因:

      1. 它们非常快,因为几乎所有 CPU 都有移位寄存器,这意味着移位操作是在硬件中完成的,只需最少的工作量(周期)。

      2. 由于它们速度很快,许多协议和标准都旨在利用这一点。例如IP地址操作、CRC校验、图形操作等。

      【讨论】:

        【解决方案4】:

        “移位运算符本质上是“修改”数据的宽度。”

        垃圾!如果移位量大于或等于数据宽度,则结果未定义。不要期望您碰巧看到的相同“mod”操作会发生在不同的编译器或同一编译器的不同版本中,或者在同一程序中的不同转换情况下,或者当其他任何事情发生变化时。这就是“未定义”的意思。

        【讨论】:

        • 实际上 C# 4.0 语言规范说: 1) 当 x 的类型是 int 或 uint 时,移位计数由计数的低五位给出。换句话说,移位计数是从 count & 0x1F 计算出来的。 2)当x的类型为long或ulong时,移位计数由count的低六位给出。换句话说,移位计数是从 count & 0x3F 计算出来的。
        猜你喜欢
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        • 2010-10-10
        • 1970-01-01
        • 2012-04-15
        • 2013-07-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多