• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

azy-blog

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

Go 语言位运算符全面总结

Go 语言位运算符全面总结

📊 位运算符速查表

运算符 名称 示例 结果 记忆技巧
& 位与 (AND) 1010 & 1100 1000 都为1才是1
| 位或 (OR) 1010 | 1100 1110 有1就是1
^ 位异或 (XOR) 1010 ^ 1100 0110 不同为1
&^ 位清除 (AND NOT) 1010 &^ 1100 0010 清除右边为1的位
<< 左移 0011 << 2 1100 乘以2^n
>> 右移 1100 >> 2 0011 除以2^n
^(一元) 位取反 (NOT) ^1010 ...0101 0变1,1变0

🔍 详细功能解析

1. 位与 & - 按位与

// 功能:两个位都为1时结果为1,否则为0
func bitwiseAND() {
    a := 0b1010  // 10
    b := 0b1100  // 12
    result := a & b  // 0b1000 = 8
    
    fmt.Printf("%04b & %04b = %04b\n", a, b, result)
    // 输出: 1010 & 1100 = 1000
    
    // 应用场景:
    // 1. 检查特定位是否为1
    flags := 0b1101
    mask := 0b0100  // 检查第2位
    if flags & mask != 0 {
        fmt.Println("第2位是1")
    }
    
    // 2. 清除某些位(通过与0相与)
    clearMask := ^0b0010  // 1110...1101
    cleared := flags & clearMask  // 清除第1位
}

2. 位或 | - 按位或

// 功能:两个位有1个为1时结果为1
func bitwiseOR() {
    a := 0b1010  // 10
    b := 0b1100  // 12
    result := a | b  // 0b1110 = 14
    
    fmt.Printf("%04b | %04b = %04b\n", a, b, result)
    // 输出: 1010 | 1100 = 1110
    
    // 应用场景:
    // 1. 设置特定位为1
    flags := 0b0000
    setMask := 0b0010
    flags = flags | setMask  // 设置第1位为1
    
    // 2. 组合多个标志
    read := 1 << 0  // 0001
    write := 1 << 1 // 0010
    exec := 1 << 2  // 0100
    permissions := read | write | exec  // 0111
}

3. 位异或 ^ - 按位异或

// 功能:两个位不同时结果为1,相同时为0
func bitwiseXOR() {
    a := 0b1010  // 10
    b := 0b1100  // 12
    result := a ^ b  // 0b0110 = 6
    
    fmt.Printf("%04b ^ %04b = %04b\n", a, b, result)
    // 输出: 1010 ^ 1100 = 0110
    
    // 应用场景:
    // 1. 切换位(0变1,1变0)
    flags := 0b1010
    toggleMask := 0b0011
    toggled := flags ^ toggleMask  // 1001
    
    // 2. 交换两个数(不用临时变量)
    x, y := 5, 9
    x = x ^ y
    y = x ^ y
    x = x ^ y
    // 现在 x=9, y=5
    
    // 3. 加密/解密(相同密钥两次异或得到原值)
    data := 42
    key := 123
    encrypted := data ^ key
    decrypted := encrypted ^ key  // 变回42
}

4. 位清除 &^ - AND NOT(Go特有)

// 功能:清除a中在b里为1的位
func bitwiseAndNot() {
    a := 0b1010  // 10
    b := 0b1100  // 12
    result := a &^ b  // 0b0010 = 2
    
    fmt.Printf("%04b &^ %04b = %04b\n", a, b, result)
    // 输出: 1010 &^ 1100 = 0010
    
    // 等价于:a & (^b)
    // 但比 ^ 优先级高,更安全
    
    // 应用场景:
    // 1. 清除特定标志位
    flags := 0b1111
    clearMask := 0b1010
    cleared := flags &^ clearMask  // 0101
    
    // 2. 从集合中移除元素(差集)
    setA := 0b1101  // 元素 {0, 2, 3}
    setB := 0b0110  // 元素 {1, 2}
    diff := setA &^ setB  // 1101,移除交集
}

5. 左移 << - 向左移位

// 功能:所有位向左移动,右侧补0
func leftShift() {
    x := 0b0001  // 1
    result := x << 3  // 0b1000 = 8
    
    fmt.Printf("%04b << 3 = %04b (%d)\n", x, result, result)
    // 输出: 0001 << 3 = 1000 (8)
    
    // 应用场景:
    // 1. 快速乘以2的幂
    n := 5
    doubled := n << 1  // 10
    times8 := n << 3   // 40
    
    // 2. 创建位掩码
    bit3 := 1 << 3  // 00001000
    bits2and3 := (1<<2) | (1<<3)  // 00001100
    
    // 3. 标志位定义
    const (
        FlagA = 1 << iota  // 1
        FlagB              // 2
        FlagC              // 4
        FlagD              // 8
    )
}

6. 右移 >> - 向右移位

// 功能:所有位向右移动
func rightShift() {
    x := 0b1000  // 8
    result := x >> 2  // 0b0010 = 2
    
    fmt.Printf("%04b >> 2 = %04b (%d)\n", x, result, result)
    // 输出: 1000 >> 2 = 0010 (2)
    
    // 注意:有符号数和无符号数右移行为不同!
    // 无符号数:左侧补0
    // 有符号数:左侧补符号位(算术右移)
    
    var u uint8 = 0b10000000  // 128
    var s int8 = -128          // 二进制也是10000000
    
    fmt.Printf("无符号: %08b >> 1 = %08b (%d)\n", u, u>>1, u>>1)
    fmt.Printf("有符号: %08b >> 1 = %08b (%d)\n", byte(s), s>>1, s>>1)
    
    // 应用场景:
    // 1. 快速除以2的幂(无符号数)
    n := 16
    half := n >> 1  // 8
    
    // 2. 提取特定位
    value := 0b11010110
    bit3 := (value >> 3) & 1  // 提取第3位
    
    // 3. 分解字节
    rgb := 0xFF3366
    r := (rgb >> 16) & 0xFF  // 红色分量
    g := (rgb >> 8) & 0xFF   // 绿色分量
    b := rgb & 0xFF          // 蓝色分量
}

7. 位取反 ^ - 一元运算符

// 功能:所有位取反(0变1,1变0)
func bitwiseNOT() {
    x := uint8(0b00001111)  // 15
    result := ^x  // 0b11110000 = 240
    
    fmt.Printf("^%08b = %08b\n", x, result)
    // 输出: ^00001111 = 11110000
    
    // 注意:Go中^既是一元也是二元运算符
    // 一元:位取反
    // 二元:异或
    
    // 应用场景:
    // 1. 创建掩码的反码
    mask := 0b00001111
    invertedMask := ^mask  // 11110000
    
    // 2. 求补码(有符号数)
    // Go中整数以补码形式存储
    
    // 3. 清除特定位(与&^配合)
    flags := 0b1111
    keepMask := 0b1100  // 保留高2位
    cleared := flags & ^keepMask  // 清除低2位
}

📊 组合使用示例

示例1:权限系统

// 使用位运算实现权限控制
const (
    Read   = 1 << iota  // 0001
    Write               // 0010
    Execute             // 0100
    Delete              // 1000
)

type User struct {
    permissions byte
}

func (u *User) addPermission(perm byte) {
    u.permissions |= perm  // 设置位
}

func (u *User) removePermission(perm byte) {
    u.permissions &^= perm  // 清除位
}

func (u *User) hasPermission(perm byte) bool {
    return u.permissions & perm != 0  // 检查位
}

func (u *User) togglePermission(perm byte) {
    u.permissions ^= perm  // 切换位
}

示例2:位标志操作

func bitFlagOperations() {
    // 初始化标志
    var flags uint8 = 0
    
    // 设置标志
    flags |= 0b00000001  // 设置第0位
    flags |= 0b00000100  // 设置第2位
    fmt.Printf("设置后: %08b\n", flags)  // 00000101
    
    // 检查标志
    if flags & 0b00000100 != 0 {
        fmt.Println("第2位已设置")
    }
    
    // 清除标志
    flags &^= 0b00000001  // 清除第0位
    fmt.Printf("清除后: %08b\n", flags)  // 00000100
    
    // 切换标志
    flags ^= 0b00001000  // 切换第3位
    fmt.Printf("切换后: %08b\n", flags)  // 00001100
    
    // 获取所有设置的位
    for i := 0; i < 8; i++ {
        if flags & (1 << i) != 0 {
            fmt.Printf("位 %d 已设置\n", i)
        }
    }
}

示例3:颜色操作(RGBA)

func colorOperations() {
    // 32位ARGB颜色:A R G B 各8位
    color := uint32(0xFF336699)  // Alpha=FF, R=33, G=66, B=99
    
    // 提取各分量
    alpha := (color >> 24) & 0xFF
    red := (color >> 16) & 0xFF
    green := (color >> 8) & 0xFF
    blue := color & 0xFF
    
    fmt.Printf("A=%02X R=%02X G=%02X B=%02X\n", alpha, red, green, blue)
    
    // 修改分量
    // 将红色分量改为0xAA
    color = (color & 0xFF00FFFF) | (0xAA << 16)
    
    // 降低亮度(所有分量减半)
    color = ((color >> 1) & 0x7F7F7F7F) | (alpha << 24)
    
    // 创建新颜色
    newColor := (0xFF << 24) | (0x12 << 16) | (0x34 << 8) | 0x56
}

🎯 优先级和结合性

优先级 运算符 说明
1 ^(一元) 位取反
2 << >> 移位
3 & 位与
4 ^(二元) 位异或
5 | 位或
6 &^ 位清除

使用括号明确优先级:

// 容易混淆的表达式
result1 := a & b ^ c   // (a & b) ^ c
result2 := a & (b ^ c) // 不同的结果!

// 总是使用括号使意图明确
clear := (a & ^b)      // 与 a &^ b 相同

💡 实用技巧

1. 判断奇偶性

func isEven(n int) bool {
    return n & 1 == 0  // 比 n%2 == 0 更快
}

2. 交换两个变量

func swap(a, b int) (int, int) {
    a ^= b
    b ^= a
    a ^= b
    return a, b  // 不用临时变量
}

3. 判断是否是2的幂

func isPowerOfTwo(n int) bool {
    return n > 0 && (n & (n-1)) == 0
}

4. 获取最低位的1

func lowestSetBit(n int) int {
    return n & -n  // 如:1010 & 0110 = 0010
}

5. 统计1的个数(Brian Kernighan算法)

func countOnes(n uint) int {
    count := 0
    for n != 0 {
        n &= n - 1  // 清除最低位的1
        count++
    }
    return count
}

posted on 2026-01-17 13:59  ikun404  阅读(1)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3