跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

C#中移位运算详解_C#左移右移操作教程【详解】

<< 和 >> 是底层位操作,实际移位数由右操作数低5位(int)或低6位(long)决定,负移位数被禁止,>> 对负数为算术右移,小类型移位前自动提升为int易致符号扩展。 直接说结论:
<<
和
>>
不是简单的“乘2”或“除2”快捷写法,它们是底层位操作,行为由操作数类型和移位数的**低5位或低6位**决定,超出范围的移位数会被自动截断——这是绝大多数人踩坑的根源。 为什么
i << 33
和
i << 1
结果一样? 因为
i
是
int
(32位),C# 规定:实际移位数只取右操作数的**低5位**。33 的二进制是
100001
,低5位是
00001
(即 1),所以
i << 33
等价于
i << 1
。 对
int
或
uint
:移位数 =
rightOperand & 0x1F
(即 % 32,但不是取模,是位与) 对
long
或
ulong
:移位数 =
rightOperand & 0x3F
(即 % 64) 右操作数为负数?编译不通过——C# 明确禁止负移位数 移位后高位溢出的部分直接丢弃,不会抛异常,也不会溢出检查(
checked
也无效)
>>
对负数是算术右移,不是逻辑右移
>>
在 C# 中始终是**带符号右移**(arithmetic shift)。对负数,高位补的是符号位(1),不是 0。这意味着它不等价于数学上的整除,尤其在负数场景下结果容易误判。 C知道 CSDN推出的一款AI技术问答工具 下载
-8 >> 1
→ 结果是
-4
(二进制
11111000 >> 1 → 11111100
),符合预期
-1 >> 3
→ 仍是
-1
(全 1 的补码不断补 1) 需要无符号右移?用
(uint)x >> n
或
(ulong)x >> n
强制转成无符号类型再移 别试图用
>>
做“清空高位”或“提取字节”,它依赖符号,行为不稳定 byte/short/char 移位后自动升为 int,小心隐式类型转换 如果你写
byte b = 1; int x = b << 2;
,表面上看没问题,但中间过程是:
b
先被提升为
int
,再左移,结果也是
int
。这在组合位运算时极易引发意料外的符号扩展或高位污染。
byte b = 0b1000_0000; int r = b << 1;
→
r == -256
,不是
256
!因为
b
提升为
int
后是
0x00000080
,左移 1 变成
0x00000100
(256),但若你误以为它还是 byte 范围,就错了 想保持低位字节操作?显式用
(byte)(b << 2)
截断,或直接用
ushort
/
uint
避免符号干扰 涉及多个小整型拼包(如协议解析)时,优先统一用
uint
或
int
,避免反复 cast 最常被忽略的一点:移位数本身不参与类型推导,它必须是
int
或可隐式转为
int
的类型;而左操作数类型直接决定“取多少位做移位计数”——这个规则藏在 IL 层,运行时不会报错,只会静默截断。写位运算前,先盯住两个操作数的类型。

相关文章