zoukankan      html  css  js  c++  java
  • 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'
    
    
  • 相关阅读:
    【并发】基于 @Async和 CompletableFuture 实现并发异步操作
    【HTTP】使用 RestTemplete 实现 post请求
    【AICC】2019训练营笔记
    【Hadoop】CDH、Presto配置问题
    【Linux】文件拷贝-Linux当前目录所有文件移动到上一级目录(转)
    【Linux】linux ln文件夹的链接(转)
    【Hadoop】新建hadoop用户以及用户组,给予sudo权限(转)
    【Centos】桌面安装(转)
    【CentOS7】CentOS7各个版本镜像下载地址(转)
    【Spark】ScalaIDE运行spark,A master URL must be set in your configuration
  • 原文地址:https://www.cnblogs.com/fanzou/p/13100137.html
Copyright © 2011-2022 走看看