2012-03-27 57 views
2

我在我的C#应用​​程序中试图打包整数,但移位运算符行为奇怪的方法。
下面的代码中的注释显示了执行该行后调试器看到的代码内容。以下代码中按位运算符的奇怪行为的原因是什么?

 long code = 0;   //0x0000000000000000 
     code += (0x1111 << 32); //0x0000000000001111 
     code += (0x2222 << 16); //0x0000000022221111 
     code += (0x3333);  //0x0000000022224444 

拍摄第一线,我希望包含在括号将首先执行的代码,这将导致在0x1111被左移32位左,但它不是,但对下一行的移位发生,并在正确的位置(即0x2222必须在添加之前移位,否则结果将为0x33330000)。

我对运营商错过了什么解释?

+1

变量'code'是一个很长的值,你为什么假设0x1111是一个很长的值? – 2012-03-27 12:50:31

+0

'0x1111' *被左移了32位。恰好如此,这相当于左移了0. – harold 2012-03-27 15:32:03

回答

6

你错过了什么是整数该位移位操作模32.由于0x1111int,操作0x1111 << (32 % 32),这是0x1111 << 0,这仅仅是0x1111

你可能想要的是0x1111L << 32

从C#规范的第7.9节:

  • 当x的类型是intuint,移位计数由低阶的count五个比特给出。换句话说,移位计数从count & 0x1F计算。

  • 当x的类型是longulong时,移位计数由count的低位6位给出。换句话说,移位计数从count & 0x3F计算。

在一些硬件体系结构中,通过32移位一个int将产生0,而其它体系结构将产生相同的INT。为了保持一致的行为,C#的设计者必须选择其中一个选项。当前的行为只需要在结构的移位计数上执行& 0x1F,否则结果为0.然而,总是返回0将需要比较和产生int的体系结构上的分支。由于分支往往是昂贵的,因此他们选择大多数情况下速度最快的选项是合理的。

+0

并且您可以使用0x1111L来修复它。 – 2012-03-27 12:55:09

+0

@加贝谢谢你!就是这样,并宣布亨克说或铸造到一个预期的效果。 (对我来说,big * facepalm *) – sebf 2012-03-27 13:03:17

+0

(并且感谢您更新关于计数如何以及为什么被屏蔽的额外信息,它总是有趣的,以了解行为背后的细节) – sebf 2012-03-27 13:05:56

1

我认为这是因为0x1111被视为int

相关问题