位移极限?

Bit shifting limit?

我正在尝试根据 CIDR 表示法 eq 创建子网掩码。 /8 表示前 8 位为 1。我通过左移实现了这一点(我在这里使用 32 位)(uint)(0xffffffff << (32-8)).

代码工作正常,直到我得到一个 /0 掩码导致代码 (uint)(0xffffffff << 32)

现在左移 (uint)(0xffffffff << 31) 按预期工作 10000000.00000000.00000000.00000000

但是左移 (uint)(0xffffffff << 32) 得到 11111111.11111111.11111111.11111111。虽然预期结果将是 00000000.00000000.00000000.00000000.

最简单的解决方法是什么?使用 if 语句处理 /0 并将所有设置为 0?

我会说正确的算法应该是这样的:

0xffffffff & (uint)((((ulong)0x1 << mask) - 1) << (32-mask))

其中 mask 是 /

之后的数字

我在这里用 c# 实现了它(因为您没有指定语言),并且似乎有效:https://dotnetfiddle.net/j1IfZP

来自documentation

The left-shift operation discards the high-order bits that are outside the range of the result type and sets the low-order empty bit positions to zero

这意味着对于32位类型的左移,只取移位计数中的低5位。由于 32 = 0b10_0000 需要 6 位来存储,并且在屏蔽掉低 5 位后它将变为零。所以 0xffffffff << 32 等同于 0xffffffff << 0

要解决这个问题,您要么需要以更高的精度移动

return (uint)(((1UL << mask) - 1) << (32 - mask))

或者换档前检查换档次数

return mask == 0 ? 0xFFFFFFFFU : 0xFFFFFFFFU << (32 - mask);

后者在 32 位平台上更好