前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 指针、uintptr、unsafe.Pointer之间如何转换

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

原创
作者头像
小许code
发布2023-02-07 10:15:37
1.2K0
发布2023-02-07 10:15:37
举报
文章被收录于专栏:小许code小许code

普通指针(*T)

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

代码语言:javascript
复制
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

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

源代码中的定义如下。

代码语言:javascript
复制
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功能介绍

unsafe.Pointer定义如下,可以指向任意类型的int指针。不能进行指针运算,不能读取内存存储的值(想读取的话需要转成相对应类型的指针)。

代码语言:javascript
复制
type Pointer *ArbitraryType

type ArbitraryType int

编辑

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

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

代码语言:javascript
复制
==unsafe包的几个函数==

//返回一个变量占用的内存字节数
func Sizeof(x ArbitraryType) uintptr

//返回结构体某个字段的地址相对于此结构体起始地址的偏移量
func Offsetof(x ArbitraryType) uintptr

//返回对齐系数
func Alignof(x ArbitraryType) uintptr

指针和unsafe.Pointer的转换

举些栗子:

代码语言:javascript
复制
a := int64(100)
var ptr *int
ptr = (*int)(unsafe.Pointer(&a))
fmt.Printf("%d\n", *ptr) //输出100 如果是int32输出一个很大值

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

代码语言:javascript
复制
type People struct {
     age    int32
     height int64
}
var p = new(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 变量的偏移量

uintptr和unsafe.Pointer的转换

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

代码语言:javascript
复制
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之间的转换有点绕,相信看完这个会对这个有一个非常清晰的了解。大家可以动手试试

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 普通指针(*T)
  • uintptr
  • unsafe.Pointer
  • 指针和unsafe.Pointer的转换
  • uintptr和unsafe.Pointer的转换
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档