Go 指针、uintptr、unsafe.Pointer之间如何转换

作者:

文章目录
  • 普通指针类型,用于传递对象地址,不能进行指针运算 a := 10 var b *int //int类型指针 b = &a fmt.Println(“a=”, a) // a=10 fmt.Println(“b=”, b) // b=0xc000225530 输出的是a的地址 fmt.Println(“c=”, *b) // c=10 对a的地址进行取值
  • uintptr是一个无符号的整型,它可以保存一个指针地址,它可以进行指针运算。想取值需要转成unsafe.Pointer后, 需再转到相对应的指针类型。 源代码中的定义如下。 package builtin //uintptr is an integer type that is large enough to hold the bit pattern of any pointer. //uintptr是一个能足够容纳指针位数大小的整数类型 type uintptr uintptr
  • unsafe.Pointer功能介绍 unsafe.Pointer定义如下,可以指向任意类型的int指针。不能进行指针运算,不能读取内存存储的值(想读取的话需要转成相对应类型的指针)。它是桥梁,让任意类型的指针实现相互转换, 也可以转换成uintptr 进行指针运算。 type Pointer *ArbitraryType type ArbitraryType int unsafe.Pointer作为桥梁实现相互转换 unsafe.Pointer在unsafe包中还有以下几个函数在我们计算可能会用到 ==unsafe包的几个函数== //返回一个变量占用的内存字节数 func Sizeof(x ArbitraryType) uintptr //返回结构体某个字段的地址相对于此结构体起始地址的偏移量 func Offsetof(x ArbitraryType) uintptr //返回对齐系数 func Alignof(x ArbitraryType) uintptr
  • 举些栗子: a := int64(100) var ptr *int ptr = (*int)(unsafe.Pointer(&a)) fmt.Printf(“%dn”, *ptr) //输出100 如果是int32输出一个很大值 这是个将int64转换为int的场景,如果是int32的话转换起来会出问题,因为存在转换后的类型大于转换前的类型。如果是结构体的话,我们可以用到unsafe.Offsetof函数来计算 type People struct { age int32 height int64 } var p = &People height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height)) *((*int)(height)) = 100 //将height的值改为100 //uintptr(unsafe.Pointer(p)) 获取了 w 的指针起始值 //unsafe.Offsetof(w.p) 获取 b 变量的偏移量
  • 同样举个栗子,结合上面的People结构体的操作,对unsafe.Pointer和uintptr的转换做一个详细的说明,对加深理解非常清晰明了。 var p = &People height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height)) *((*int)(height)) = 100 //将height的值改为100 上面的代码可以理解为以下步骤: 要想修改People结构体的height的值,首先unsafe.Pointer(p),转换为uintptr 通过unsafe.Offsetof获取height的偏移量,两者都是uintptr,可进行运算得到height的地址 unsafe.Pointer将height的地址转为uintptr 先转为*int指针,然后获得height的值并赋值100
  • 指针、uintptr、unsafe.Pointer之间的转换有点绕,相信看完这个会对这个有一个非常清晰的了解。大家可以动手试试 到此这篇关于Go 指针、uintptr、unsafe.Pointer之间如何转换的文章就介绍到这了,更多相关Go 指针 uintptr unsafe.Pointer内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Golang 中的 unsafe.Pointer 和 uintptr详解 Go语言普通指针unsafe.Pointer uintpt之间的关系及指针运算 初探GO中unsafe包的使用
  • 目录
    • 普通指针(*T)
    • uintptr
    • unsafe.Pointer
    • 指针和unsafe.Pointer的转换
    • uintptr和unsafe.Pointer的转换
    • 总结

    普通指针类型,用于传递对象地址,不能进行指针运算

    	a := 10
    	var b *int  //int类型指针
    	b = &a
    	fmt.Println("a=", a)  // a=10
    	fmt.Println("b=", b)  // b=0xc000225530 输出的是a的地址
    	fmt.Println("c=", *b) // c=10  对a的地址进行取值
    

    uintptr是一个无符号的整型,它可以保存一个指针地址,它可以进行指针运算。想取值需要转成unsafe.Pointer后, 需再转到相对应的指针类型。

    源代码中的定义如下。

    package builtin
    
    //uintptr is an integer type that is large enough to hold the bit pattern of any pointer.
    //uintptr是一个能足够容纳指针位数大小的整数类型
    type uintptr uintptr
    

    unsafe.Pointer功能介绍

    unsafe.Pointer定义如下,可以指向任意类型的int指针。不能进行指针运算,不能读取内存存储的值(想读取的话需要转成相对应类型的指针)。
    它是桥梁,让任意类型的指针实现相互转换, 也可以转换成uintptr 进行指针运算。

    type Pointer *ArbitraryType
    
    type ArbitraryType int
    

    unsafe.Pointer作为桥梁实现相互转换

    unsafe.Pointer在unsafe包中还有以下几个函数在我们计算可能会用到

    ==unsafe包的几个函数==
    
    //返回一个变量占用的内存字节数
    func Sizeof(x ArbitraryType) uintptr
    
    //返回结构体某个字段的地址相对于此结构体起始地址的偏移量
    func Offsetof(x ArbitraryType) uintptr
    
    //返回对齐系数
    func Alignof(x ArbitraryType) uintptr
    

    举些栗子:

    	a := int64(100)
    	var ptr *int
    	ptr = (*int)(unsafe.Pointer(&a))
    	fmt.Printf("%dn", *ptr) 
    	//输出100 如果是int32输出一个很大值
    	
    

    这是个将int64转换为int的场景,如果是int32的话转换起来会出问题,因为存在转换后的类型大于转换前的类型。
    如果是结构体的话,我们可以用到unsafe.Offsetof函数来计算

        type People struct {
    	    age    int32
    	    height int64
        }
        var p = &People
    	height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height))
    	*((*int)(height)) = 100 //将height的值改为100
    	//uintptr(unsafe.Pointer(p)) 获取了 w 的指针起始值
        //unsafe.Offsetof(w.p) 获取 b 变量的偏移量
    

    同样举个栗子,结合上面的People结构体的操作,对unsafe.Pointer和uintptr的转换做一个详细的说明,对加深理解非常清晰明了。

        var p = &People
    	height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height))
    	*((*int)(height)) = 100 //将height的值改为100
    

    上面的代码可以理解为以下步骤:

    1. 要想修改People结构体的height的值,首先unsafe.Pointer(p),转换为uintptr
    2. 通过unsafe.Offsetof获取height的偏移量,两者都是uintptr,可进行运算得到height的地址
    3. unsafe.Pointer将height的地址转为uintptr
    4. 先转为*int指针,然后获得height的值并赋值100

    指针、uintptr、unsafe.Pointer之间的转换有点绕,相信看完这个会对这个有一个非常清晰的了解。大家可以动手试试

    到此这篇关于Go 指针、uintptr、unsafe.Pointer之间如何转换的文章就介绍到这了,更多相关Go 指针 uintptr unsafe.Pointer内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Golang 中的 unsafe.Pointer 和 uintptr详解
    • Go语言普通指针unsafe.Pointer uintpt之间的关系及指针运算
    • 初探GO中unsafe包的使用

    站内搜索