本教程正在对整个子网掩码进行-not,因此ff00 反转为00ff,对于更长的Fs 和0s 类似;你没有这样做,所以你不会得到相同的结果。
您显示的完全扩展的计算正在执行此操作:
1. (2001:0db8:1234:0000:0000:0000:0000:0000) | ~(ffff:ffff:ffff:0000:0000:0000:0000:0000)
2. (2001:0db8:1234:0000:0000:0000:0000:0000) | (0000:0000:0000:ffff:ffff:ffff:ffff:ffff)
3. = 2001:db8:1234:ffff:ffff:ffff:ffff:ffff
注意在第 1 步到第 2 步中,not 如何反转 Fs 和 0s 的模式,切换子网掩码,并在前缀结束的 bit 之间切换以及主机部分开始的位。
然后第 3 步 or 仅采用左侧的设置位以保持这些数字相同(既不是零也不是 ffff'd),所有是右侧的设置位( ffff 这些,将它们最大化到该前缀内的最大 IP 地址)。
换句话说,“一次一个八位字节”这样做是没有意义的。这是一个完整的IP地址(或整个前缀)+整个子网掩码的操作。
教程说的地方:
& (AND), | (OR), ~ (NOT or bit INVERTER):我们将在计算中使用这三个位运算符。我认为每个人都熟悉——至少从大学数字逻辑课程中——并且知道它们是如何运作的。此处不再详细说明。您可以搜索“按位运算符”以获取更多信息。
如果您对它们的工作不是很熟悉,那么在尝试将它们应用于 IP 子网划分之前,值得进一步研究。因为您基本上是在问为什么 0 or (not 1) 是 0 而答案是因为这就是布尔逻辑“或”和“非”的工作方式。
编辑您的评论
[math]::pow(2,128) 比 [decimal]::maxvalue 大很多,所以我认为 Decimal 不会。
我不知道推荐的方法是什么,但我想如果您真的想在 PowerShell 中使用 -not 完成所有操作,您必须使用 [bigint] 处理它(例如 [bigint]::Parse('20010db8123400000000000000000000', 'hex') )。
但更有可能的是,你会做一些更冗长的事情,比如:
# parse the address and mask into IP address objects
# which saves you having to expand the short version to
$ip = [ipaddress]::Parse('fe80::1')
$mask = [ipaddress]::Parse('ffff::')
# Convert them into byte arrays, then convert those into BitArrays
$ipBits = [System.Collections.BitArray]::new($ip.GetAddressBytes())
$maskBits = [System.Collections.BitArray]::new($mask.GetAddressBytes())
# ip OR (NOT mask) calculation using BitArray's own methods
$result = $ipBits.Or($maskBits.Not())
# long-winded way to get the resulting BitArray back to an IP
# via a byte array
$byteTemp = [byte[]]::new(16)
$result.CopyTo($byteTemp, 0)
$maxIP = [ipaddress]::new($byteTemp)
$maxIP.IPAddressToString
# fe80:ffff:ffff:ffff:ffff:ffff:ffff:ffff