我的C#应用程序中有一个方法试图打包一个整数,但是移位运算符表现得很奇怪。
下面代码中的注释显示了执行行后调试器看到的代码内容。
long code = 0; //0x0000000000000000
code += (0x1111 << 32); //0x0000000000001111
code += (0x2222 << 16); //0x0000000022221111
code += (0x3333); //0x0000000022224444
从第一行开始,我希望括号中包含的代码将首先被执行,这将导致0x1111向左移位32位,但它不是,但在下一行,转移确实发生,并且在正确的位置(即在添加之前必须移位0x2222,否则结果将是0x33330000)。
对于解释此问题的运营商,我有什么遗漏?
答案 0 :(得分:6)
你错过的是对int的位移操作是mod 32.由于0x1111
是int
,操作是0x1111 << (32 % 32)
,即0x1111 << 0
,这是只是0x1111
。
您可能想要的是0x1111L << 32
。
来自C#规范的第7.9节:
当x的类型为
int
或uint
时,移位计数由count
的低位5位给出。换句话说,班次计数是从count & 0x1F
计算的。当x的类型为
long
或ulong
时,移位计数由count
的低位6位给出。换句话说,班次计数是从count & 0x3F
计算的。
在某些硬件架构上,将int移位32将产生0,而其他架构将产生相同的int。为了保持一致的行为,C#的设计者必须选择其中一个选项。当前行为只需要对体系结构上的移位计数执行& 0x1F
,否则会产生0.然而,总是返回0将需要比较和产生int的体系结构上的分支。由于分支往往价格昂贵,因此在大多数情况下选择最快的选项是有道理的。
答案 1 :(得分:1)
我相信它是因为0x1111
被视为int
。