【问题标题】:Bit shifting limit?位移限制?
【发布时间】:2020-10-17 10:13:09
【问题描述】:

我正在尝试从 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?

【问题讨论】:

    标签: c# bit bit-shift bitmask cidr


    【解决方案1】:

    来自documentation

    左移操作丢弃超出结果类型范围的高位,并将低位空位位置设置为零

    这意味着对于 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 位平台上更好

    【讨论】:

      【解决方案2】:

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

      0xffffffff &amp; (uint)((((ulong)0x1 &lt;&lt; mask) - 1) &lt;&lt; (32-mask))

      mask 是 / 后面的数字

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

      【讨论】:

      • 0xffffffff &amp; 部分是多余的,因为转换为 uint 已经截断到低 32 位
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-05
      • 2011-06-26
      • 1970-01-01
      • 2022-11-19
      • 2019-06-30
      • 1970-01-01
      相关资源
      最近更新 更多