• go普通指针、unsafe.Poniter、unintptr之间的联系


    go普通指针、unsafe.Poniter、unintptr之间的联系

    GO指针

    . 普通指针 *type 普通指针,用于传递对象地址,不能进行指针运算
    . unsafe.Poniter 通用型指针,用于不同类型指针的转换,不能进行指针运算,不能读取内存存储的值
    . unintptr 可进行指针运算,由于其无法持有对象,GC不把unintptr当作指针,unintptr常被回收

    unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为 uintptr 进行指针运算。
    只有uintptr类型才可以进行运算,只要将普通指针类型转换成uintptr类型,做完加减法后,再转换成普通指针,通过*操作,取值,修改值,随意。
    总结:unsafe.Pointer 可以让你的变量在不同的普通指针类型转来转去,也就是表示为任意可寻址的指针类型。而 uintptr 常用于与 unsafe.Pointer 打配合,用于做指针运算

    unsafe.Pointer

    • 用于各种指针相互转换的桥梁,它可以包含任意类型变量的地址
    • 当然,我们不可以直接通过*p来获取unsafe.Pointer指针指向的真实变量的值,因为我们并不知道变量的具体类型。
    • 和普通指针一样,unsafe.Pointer指针也是可以比较的,并且支持和nil常量比较判断是否为空指针。

    uintptr

    • uintptr是一个整数类型。即使uintptr变量仍然有效,由uintptr变量表示的地址处的数据也可能被GC回收,这个需要注意!

    unsafe包

    -unsafe包只有两个类型,三个函数

    type ArbitraryType int
    type Pointer *ArbitraryType
    func Sizeof(x ArbitraryType) uintptr //返回其占用的字节数
    func Offsetof(x ArbitraryType) uintptr  //返回结构体中元素所在的内存的偏移量
    func Alignof(x ArbitraryType) uintptr  //返回变量对齐字节数量
    

    -三个函数的参数均是ArbitraryType类型,就是接受任何类型的变量。

    运用

    unsafe.pointer用于普通指针类型转换

    v1 := int(12)
    p = (*uint)(unsafe.Pointer(&v2))
    

    unsafe.pointer用于访问操作结构体的私有变量

    type V struct {
        i int32
        j int64
    }
    
    func main() {
        var v *V = new(V)
        var i *int32 = (*int32)(unsafe.Pointer(v))
        *i = int32(98)
        var j *int64 = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int32(0)))))
        *j = int64(763)
        v.PutI()
        v.PutJ()
    } 
    
    func main() {
        var b []byte = []byte{'a', 'b', 'c'}
        var c *byte = &b[0]
        fmt.Println(*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + uintptr(1))))
    }
    
    //错误写法,不要试图引入一个uintptr类型的临时变量,因为它可能会破坏代码的安全性,随时可能被GC回收影响
    tmp := uintptr(unsafe.Pointer(c)) + uintptr(1)
    pb := (*byte)(unsafe.Pointer(tmp))
    *pb = 'd'
    
    
  • 相关阅读:
    C#中的运算符和表达式
    C#的常量和变量以及其作用域和命名规范
    C#中(int)、int.Parse()、int.TryParse()和Convert.ToInt32()的区别
    在咸阳机场等候登机有感
    关于博客的回忆
    String、StringBuffer、StringBuilder有什么区别
    谈谈你对Java异常处理机制的理解
    谈谈你对 Java 平台的理解?
    所谓的产品经理
    mysql数据库开发常见问题及优化
  • 原文地址:https://www.cnblogs.com/fanzou/p/13100137.html
Copyright © 2020-2023  润新知