0%

go位操作

看mutex源码时,发现有很多的位操作,记一下加深印象

位运算都是在二进制的基础上进行运算的,所以在位运算之前要先将两个数转成二进制

<< >> 左移和右移运算符

左移运算符 << 是双目运算符。左移n位就是乘以2的n次方,其功能是把 << 左边的运算数的各二进位全部左移若干位,由 << 右边的数指定移动的位数,高位丢弃,低位补0
右移运算符 >> 是双目运算符。右移n位就是除以2的n次方,其功能是把 >> 左边的运算数的各二进位全部右移若干位,由 >> 右边的数指定移动的位数,低位丢弃,高位补0
应用举例:

1
2
3
4
5
6
7
8
const (
B = 1 << (10 * iota) // 1<<(10*0)
KB // 1<<(10*1) 1024B
MB // 1<<(10*2) 1024KB
GB // 1<<(10*3) 1024MB
TB // 1<<(10*4) 1024GB
PB // 1<<(10*5) 1024TB
)

& 位运算 AND

同一位都是1,结果才是1,否则为0

  • 清零特定位(特定位置0,其它位为1)
  • 取某数中指定位(特定位置1,其它位为0)

应用举例:

1
2
3
4
// IsOdd 判断数字是否为奇数
func IsOdd(i int)bool{
return (i & 1) == 1
}

~ 位运算 NOT

按位取反,0变1,1则变0
应用举例:
源码/补码/反码

| 位运算 OR

同一位都是0,结果才是0,否则为1

  • 将某些位置1,其它位不变

应用举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const (
mutexLocked = 1 << iota // mutex is locked
mutexWoken
mutexStarving
...
)
func (m *Mutex) lockSlow() {
old := m.state
...
new := old
// Don't try to acquire starving mutex, new arriving goroutines must queue.
if old&mutexStarving == 0 {
new |= mutexLocked // 加锁,即将对应位置为1
}
...
}

^ 异或运算 XOR

同一位相同时结果为0,否则为1

  • 将某些位翻转(特定位置1,其它位为0)
  • 交换两个值,不用临时变量
    • 异或满足交换律和结合律 x ^ x == 0 x ^ 0 == x

应用举例:

1
2
3
4
5
func Swap(a, b int){
a = a ^ b
b = a ^ b
a = a ^ b
}

&^ 位清空运算符 AND NOT

z = x &^ y 如果 y 的位为 1 那么 z 对应的位是 0,否则 z 就使用 x 对应位的值
应用举例:

1
2
3
4
5
6
func main() {
x, y, z := 42, 13, 0
z = x &^ y
fmt.Printf("%d(%08b) = %d(%08b) &^ %d(%08b) \n", z, z, x, x, y, y)
// 34(00100010) = 42(00101010) &^ 13(00001101)
}

参考链接

原文链接