以下代码中按位运算符奇怪行为的原因是什么?

seb*_*ebf 2 c# bit-manipulation

我在我的C#应用​​程序中有一个方法试图打包一个整数,但是移位运算符表现得很奇怪.
下面代码中的注释显示了执行行后调试器看到的代码内容.

        long code = 0;          //0x0000000000000000
        code += (0x1111 << 32); //0x0000000000001111
        code += (0x2222 << 16); //0x0000000022221111
        code += (0x3333);       //0x0000000022224444
Run Code Online (Sandbox Code Playgroud)

从第一行开始,我预计括号中包含的代码将首先被执行,这将导致0x1111向左移位32位,但它不是,但在下一行,移位确实发生,并且也是正确的位置(即在添加之前必须移位0x2222,否则结果将为0x33330000).

有什么我错过了解释这个的操作员?

Gab*_*abe 6

什么,你错过的是在该整数位的移位操作国防部32由于0x1111是int,该操作是0x1111 << (32 % 32),这是0x1111 << 0,这仅仅是0x1111.

你可能想要的是什么0x1111L << 32.

从C#规范的第7.9节:

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

  • 当x的类型是long或时ulong,移位计数由低位6位给出count.换句话说,移位计数是从count & 0x3F.

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