了解班次操作员

时间:2009-01-20 09:21:38

标签: c#

我无法理解这个移位运算符(c#reference):

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
*/

4 个答案:

答案 0 :(得分:44)

<<是左移算子;这将获取一个值的二进制表示,并将所有位“n”位置向左移动(“mod”除外,参见“1”),后面用零填充。

>>是右移运营商;这几乎完全相反(向右移动),除了有符号值(即那些可以是负数),它用负值反向填充1,否则为零。

1:

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

2:

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

这是简单的二进制文件:

0000000001 = 1

&LT;&LT;去

0000000010 = 2

&LT;&LT;去

0000000100 = 4

&LT;&LT;去

0000001000 = 8

答案 1 :(得分:8)

只是为了扩展Marc的答案(Marc,随意将其包括在你的内容中,我将删除这个答案)这在规范的第7.8节中有详细说明:


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

向左移动:

  • int operator&lt;&lt;(int x,int count);
  • uint operator&lt;&lt;(uint x,int count);
  • 长运算符&lt;&lt;(long x,int count);
  • ulong operator&lt;&lt;(ulong x,int count);

&lt;&lt;运算符将x向左移位如下所述计算的位数。

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

右移:

  • int operator&gt;&gt;(int x,int count);
  • uint operator&gt;&gt;(uint x,int count);
  • 长运算符&gt;&gt;(long x,int count);
  • ulong operator&gt;&gt;(ulong x,int count);

&gt;&gt;运算符将x右移一个按如下所述计算的位数。

当x为int或long类型时,x的低位被丢弃,其余位向右移位,如果x为非负,则高位空位位置设置为零并设置为一个如果x是负数。

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

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

当x的类型为int或uint时,移位计数由计数的低5位给出。换句话说,移位计数是根据计数和计算来计算的。为0x1F。

当x的类型为long或ulong时,移位计数由计数的低6位给出。换句话说,移位计数是根据计数和计算来计算的。 0x3F的。

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


答案 2 :(得分:2)

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

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

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

  2. 因为它们很快,所以很多协议和标准都是为了利用这一点而设计的。例如IP地址操作,检查CRC,图形操作等。

答案 3 :(得分:1)

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

垃圾!如果移位量大于或等于数据的宽度,则结果是不确定的。不要指望您碰巧看到的相同'mod'操作,不同编译器或同一编译器的不同版本,或同一程序中的不同移位情况,或其他任何更改时。这就是“未定义”的意思。