问题描述
我正在尝试根据CIDR表示法创建一个子网掩码。 /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
,左移操作将舍弃结果类型范围之外的高阶位,并将低阶空位位置设置为零
这意味着对于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位平台上更好