位移极限?
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
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 位平台上更好
我正在尝试根据 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
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 位平台上更好