# Go 语言中的 uintptr 和 unsafe.Pointer 区别

# 1. unsafe.Pointer

unsafe.Pointer 是 Go 语言中的特殊指针类型,它可以:

  1. 绕过 Go 的类型系统,实现任意类型指针间的转换
  2. 用于指向任意类型的指针转换模式:
*T1 -> unsafe.Pointer -> *T2
  1. 保持指针语义,会被 GC 追踪
  2. 不能直接进行指针算术运算

# 主要特点:

  • 可以存储任何类型的地址
  • 可以和普通指针互相转换
  • 保持对目标对象的引用关系
  • 参与 GC 扫描

# 2. uintptr

uintptr 是一个整数类型,它的大小足够存储一个指针的值。主要特点:

  1. 本质是一个无符号整数,而不是指针
  2. 可以进行算术运算
  3. 不会被 GC 追踪
  4. 不保证其值指向的内存对象依然有效

# 使用场景:

  • 指针偏移量计算
  • 进行地址相关的位运算
  • 存储地址的数值表示

# 3. 关键区别对比

特性 unsafe.Pointer uintptr
类型本质 指针类型 整数类型
GC 追踪
算术运算 不支持 支持
类型转换 可与任意指针类型互转 仅与整数类型互转
内存安全 相对安全 不安全

# 4. 使用示例

func example() {
    // 创建一个示例结构体
    type MyStruct struct {
        a int
        b string
    }
    
    x := &MyStruct{a: 1, b: "hello"}
    
    //unsafe.Pointer 使用
    pointer := unsafe.Pointer(x)
    
    //uintptr 使用
    address := uintptr(pointer)
    
    // 警告:以下操作可能不安全
    offsetAddress := address + unsafe.Sizeof(int(0))  // 指向 b 字段
    
    // 转回 unsafe.Pointer 必须一气呵成
    bPointer := unsafe.Pointer(offsetAddress)
    bString := (*string)(bPointer)
    
    fmt.Println(*bString) // "hello"
}

# 5. 使用注意事项

  1. 尽量避免使用 unsafe 包,除非确实需要
  2. uintptr 转换后立即使用,不要存储
  3. 指针计算必须遵循内存对齐规则
  4. GC 可能会在 uintptr 计算过程中移动对象

警告:不恰当使用 unsafe 包可能导致未定义行为,应当谨慎使用。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

ZJM 微信支付

微信支付

ZJM 支付宝

支付宝