位操作golang
Bit manipulation golang
我正在查看包含以下内容的代码库:
const IdLength = 20
type NodeID [IdLength]byte
func (node NodeID) PrefixLen() (ret int) {
for i := 0; i < IdLength; i++ {
for j := 0; j < 8; j++ {
if (node[i] >> uint8(7 - j)) & 0x1 != 0 {
return i * 8 + j;
}
}
}
return IdLength * 8 - 1;
}
我不太明白这里发生了什么。谁能举个例子给我解释一下?
这将可变数量的字节作为输入,这些字节实际上被视为位。它 return 是字节流中前导 0
位的数量。假设您有这些字节:
0x00 0x00 0x05
二进制文件看起来像这样
00000000 00000000 00000101
表示函数returns 8+8+5 = 21
.
以i
作为变量的外循环遍历所有字节,以j
作为变量的内循环遍历该字节中的所有位。它从顶部移动第 j 位,向下移动到最低位,二进制和 (&
) 与 0x01
屏蔽除最低位之外的所有内容,然后 != 0
询问该位是否是 1
在这种情况下,我们位于 0
前缀和 return 结果的末尾。
如果在函数末尾没有早期的 return,所有字节都是 0
所以它 return 是那个值。由于某种原因,这种特殊情况不是 return 208,而是 208-1。我猜这是特定于应用程序的。我本来希望它 return 全部为零,但它 return 少了一个。
这是一个代码示例,输出为注释:
package main
import "fmt"
func main() {
fmt.Println(NodeID{0xFF}.PrefixLen()) // 0
fmt.Println(NodeID{0x7F}.PrefixLen()) // 1
fmt.Println(NodeID{0x3F}.PrefixLen()) // 2
fmt.Println(NodeID{0x1F}.PrefixLen()) // 3
fmt.Println(NodeID{0x0F}.PrefixLen()) // 4
// ...
fmt.Println(NodeID{0x00, 0x00, 0x05}.PrefixLen()) // 21
// ...
fmt.Println(NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}.PrefixLen()) // 159
fmt.Println(NodeID{}.PrefixLen()) // 159
}
const IdLength = 20
type NodeID [IdLength]byte
func (node NodeID) PrefixLen() (ret int) {
for i := 0; i < IdLength; i++ {
for j := 0; j < 8; j++ {
if (node[i]>>uint8(7-j))&0x1 != 0 {
return i*8 + j
}
}
}
return IdLength*8 - 1
}
我正在查看包含以下内容的代码库:
const IdLength = 20
type NodeID [IdLength]byte
func (node NodeID) PrefixLen() (ret int) {
for i := 0; i < IdLength; i++ {
for j := 0; j < 8; j++ {
if (node[i] >> uint8(7 - j)) & 0x1 != 0 {
return i * 8 + j;
}
}
}
return IdLength * 8 - 1;
}
我不太明白这里发生了什么。谁能举个例子给我解释一下?
这将可变数量的字节作为输入,这些字节实际上被视为位。它 return 是字节流中前导 0
位的数量。假设您有这些字节:
0x00 0x00 0x05
二进制文件看起来像这样
00000000 00000000 00000101
表示函数returns 8+8+5 = 21
.
以i
作为变量的外循环遍历所有字节,以j
作为变量的内循环遍历该字节中的所有位。它从顶部移动第 j 位,向下移动到最低位,二进制和 (&
) 与 0x01
屏蔽除最低位之外的所有内容,然后 != 0
询问该位是否是 1
在这种情况下,我们位于 0
前缀和 return 结果的末尾。
如果在函数末尾没有早期的 return,所有字节都是 0
所以它 return 是那个值。由于某种原因,这种特殊情况不是 return 208,而是 208-1。我猜这是特定于应用程序的。我本来希望它 return 全部为零,但它 return 少了一个。
这是一个代码示例,输出为注释:
package main
import "fmt"
func main() {
fmt.Println(NodeID{0xFF}.PrefixLen()) // 0
fmt.Println(NodeID{0x7F}.PrefixLen()) // 1
fmt.Println(NodeID{0x3F}.PrefixLen()) // 2
fmt.Println(NodeID{0x1F}.PrefixLen()) // 3
fmt.Println(NodeID{0x0F}.PrefixLen()) // 4
// ...
fmt.Println(NodeID{0x00, 0x00, 0x05}.PrefixLen()) // 21
// ...
fmt.Println(NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}.PrefixLen()) // 159
fmt.Println(NodeID{}.PrefixLen()) // 159
}
const IdLength = 20
type NodeID [IdLength]byte
func (node NodeID) PrefixLen() (ret int) {
for i := 0; i < IdLength; i++ {
for j := 0; j < 8; j++ {
if (node[i]>>uint8(7-j))&0x1 != 0 {
return i*8 + j
}
}
}
return IdLength*8 - 1
}