我有什么方法可以使用按位运算符检查 32 位网络掩码是否有效?
我必须从 MSB 端检查“1”是否处于连续流中。 例如 11111111.0.0.0 (255.0.0.0) 有效 但 11111101.0.0.0 (253.0.0.0) 不是。
首先要做的是检查网络掩码是否非零(令人讨厌的边缘情况)。既然这样就可以了,你需要按位求逆。
uint32_t y = ~x;
然后添加一个
uint32_t z = y + 1;
那么如果
x
是一个正确的网络掩码,则最多将设置 1 位。
为了测试这一点,只需将
z
与 z - 1
相结合,恰好是 y
。如果一切正常,结果将为零,否则结果将不为零。
valid = (z & y) == 0;
要检查无效的网络掩码,您可以使用以下简单算法:
mask & (~mask >> 1)
对于无效的网络掩码,其计算结果为 1;对于有效的网络掩码,其计算结果为 0。
有效的网络掩码不能有 0 且其右侧有 1。 所有零的右侧都必须有另一个零,或者为位 0。如果您采用右侧有一个 0 的网络掩码的补码 (~),并将其向右移动一位位置,您将网络掩码中的 1 与网络掩码的移位补码中的 1 对齐。 将这两个值“与”在一起将产生一个表示网络掩码无效的值。
如果采用网络字节顺序,请务必在应用此算法之前使用 ntohl() 将网络掩码转换为主机字节顺序。 另外,如果您想排除 0xffffffff 和 0x00000000,则需要对它们进行特殊检查。
注意:由于 C 运算符的优先级和结合性规则,算法中显示的括号不是必需的,但我添加了它们是为了使代码更容易理解,以防您不总是记住优先级和结合性规则。
int is_netmask_valid(uint32_t mask)
{
if (mask == 0) return 0;
if (mask & (~mask >> 1)) {
return 0;
} else {
return 1;
}
}
~mask & -mask
呢?尽管如此, mask == 0 。
对于右侧的 mask = 0b11110000
(1 后跟 0),您将得到:
~mask = 0b00001111
-mask = 0b00010000
然后
~mask & -mask == 0
对于错误的
mask = 0b11010000
:
~mask = 0b00101111
-mask = 0b00110000
然后
~mask & -mask == 0b00100000 (!= 0)