Go 位运算
& 位运算 AND
| 位运算 OR
^ 位运算 XOR
&^ 位清空 (AND NOT)
<< 左移
>> 右移
位运算 & 的应用
package main
import (
"errors"
"fmt"
)
func readUint64Revert(buff []byte, dest *uint64) error {
if len(buff) != 8 {
return errors.New("incorrect source byte array length")
}
*dest = uint64(buff[7] & 0xFF)
*dest += uint64(buff[6]&0xFF) << 8
*dest += uint64(buff[5]&0xFF) << 16
*dest += uint64(buff[4]&0xFF) << 24
*dest += uint64(buff[3]&0xFF) << 32
*dest += uint64(buff[2]&0xFF) << 40
*dest += uint64(buff[1]&0xFF) << 48
*dest += uint64(buff[0]&0xFF) << 56
return nil
}
func main() {
mockData := []byte{0x2E, 0x4A, 0x3C, 0x00, 0x66, 0xD9, 0x1B, 0x1C}
var result uint64
err := readUint64Revert(mockData, &result)
if err != nil {
fmt.Println("error...")
return
}
fmt.Println(result)
buff := make([]byte, 4)
buff[0] = 0
buff[1] = 255
fmt.Println(buff[0], buff[1])
data01 := buff[0] & 0xff
data02 := buff[1] & 0xff
fmt.Println(data01, data02)
}
readUint64Revert 是从一个字节数组中读取一个 uint64 类型的整型。
其中 buff[7] & 0xFF 表示取字节数组的第8个元素和 0xFF 做 & 操作。
其中 0xFF 表示一个掩码,表示一个字的最低8位全是1。 比如,0x89ABCDEF & 0xFF = 0x000000EF。
位运算 ^ 的应用
按位异或运算定义,
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
异或的几个常见用途:
(1) 实现两个值的交换,而不必使用临时变量。如下代码,
package main
import "fmt"
func main() {
a := 0xA7
b := 0xA1
fmt.Println(a, b)
a ^= b
b ^= a
a ^= b
fmt.Println(a, b)
}
输出:
167 161
161 167
可以这样理解:
第一步 a^=b 即a=(a^b);
第二步 b^=a 即b=b^(a^b),由于^运算满足交换律,b^(a^b)=b^b^a。由于一个数和自己异或的结果为0并且任何数与0异或都会不变的,所以此时b被赋上了a的值。
第三步 a^=b 就是a=a^b,由于前面二步可知a=(a^b),b=a,所以a=a^b即a=(a^b)^a。故a会被赋上b的值。
再来个实例说明下以加深印象。int a = 13, b = 6;
a的二进制为 13=8+4+1=1101(二进制)
b的二进制为 6=4+2=110(二进制)
第一步 a^=b a = 1101 ^ 110 = 1011;
第二步 b^=a b = 110 ^ 1011 = 1101;即b=13
第三步 a^=b a = 1011 ^ 1101 = 110;即a=6
(2) 在汇编语言中经常用于将变量置零:
package main
import "fmt"
func main() {
a := 0xA7
b := 0xA1
fmt.Println(a, b)
a ^= a
b ^= b
fmt.Println(a, b)
}
输出:
167 161
0 0
(3) 使某些特定的位翻转
例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。
10100001^00000110 = 10100111
(4) 使用定理三进行编码解码
由B ^ A^ A = B,我们可以假设一聊天记录是B,密钥是A。现在B ^ A之后,成了密文了。为了解密,对密文再使用密钥A进行一次异或运算即可。也即是B ^ A^ A = B。
(5) 使用异或求一个数的绝对值
package main
import "fmt"
func main() {
data := -1234
i := data >> 31
result := data ^ i - i
fmt.Println(data, result)
}
位运算 &^ 的应用
此运算符是双目运算符,按位计算。主要功能:
将运算符左边数据相异的位保留,相同位清零。
fmt.Println(0 &^ 0) //0
fmt.Println(0 &^ 1) //0
fmt.Println(1 &^ 0) //1
fmt.Println(1 &^ 1) //0
==========END==========