go uintptr unsafe Pointer offset() 的使用
go语言基本类型
类型名称 | 有无符号 | 占用位数 |
int8 | Yes | 8 |
int16 | Yes | 16 |
int32 | Yes | 32 |
int64 | yes | 64 |
uint8 | No | 8 |
uint16 | No | 16 |
uint32 | No | 32 |
uint64 | No | 64 |
int | Yes | 32或64,等于cpu位数 |
uint | No | 32或64,等于cpu位数 |
rune | No | 32,与uint32等价 |
byte | No | 8,与uint8等价 |
uintptr | No | 64,与uint64等价 |
rune 类型是 Unicode 字符类型,和 uint32 类型等价,通常用于表示一个 Unicode 字符。rune 和 uint32 可以互换使用。
byte 类型与uint8类型等价,byte类型一般用于强调数值是一个原始的内存数据而不是 一个小的整数。
uintptr 是一种无符号的整数类型,与uint64等价,范围:0 ~ 18446744073709551615,足以容纳任何指针值转换来的整型值。 uintptr类型只有在底层编程是才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方。GC 不把 uintptr 当指针,uintptr 无法持有对象。uintptr 类型的目标会被回收,所以不要声明uintptr类型的变量
不管它们的具体大小,int、uint和uintptr是不同类型的兄弟类型。其中int和int32也是 不同的类型, 即使int的大小也是32bit,在需要将int当作int32类型的地方需要一个显式的类型转换操作,反之亦然
unsafe.Pointer
一个可以指向任意类型的指针,不可以进行数值计算
有四种区别于其他类型的特殊操作:
1. 任意类型的指针值均可转换为 Pointer
2. Pointer 均可转换为任意类型的指针值
3. uintptr 均可转换为 Pointer
4. Pointer 均可转换为 uintptr
unsafe 库让 golang 可以像C语言一样操作计算机内存,但这并不是golang推荐使用的,能不用尽量不用,就像它的名字所表达的一样,它绕过了golang的内存安全原则,是不安全的,容易使你的程序出现莫名其妙的问题,不利于程序的扩展与维护
示例1(unsafe.Pointer用来取地址,uintptr用来取地址的10进制数值):
package main
import ("fmt""unsafe"
)
func main() {a := int(5)p := &afmt.Println("p:", p) // a的地址,16进制形式fmt.Println("unsafe.Pointer(&a):", unsafe.Pointer(&a)) // a的地址,16进制形式fmt.Println("uintptr(unsafe.Pointer(&a)):", uintptr(unsafe.Pointer(&a))) // a的地址,10进制形式
}
结果如下图:
PS:每次运行a的地址可能是不同的,但 unsafe.Pointer(&a) 和 uintptr(unsafe.Pointer(&a))的值是一样的,只是前者是指针类型,16进制,后者是整数类型,10进制,两者相等,这里 0xc00000a0b8,转换为10进制即 824633761976
示例2(地址计算,偏移,并修改)
package main
import ("fmt""unsafe"
)
func main() {a := [4]int{0, 1, 2, 3}p1 := unsafe.Pointer(&a[1]) // p1指向a[1]的起始地址// a[1]的地址类型转换为uintptr类型,后移2个元素的位置,这样移动到a[3]的起始地址位置p3 := unsafe.Pointer(uintptr(p1) + 2 * unsafe.Sizeof(a[0]))*(*int)(p3) = 6 // 先将Pointer类型转换为*int类型,再赋值fmt.Println("a =", a) // 打印出来结果是:a = [0 1 2 6]
}
结果如下图:
PS:unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为 uintptr 进行指针运算
示例3(unsafe.Offsetof的使用)
该函数返回属性x的起始地址和结构体起始地址的字节数
func Offsetof(x ArbitraryType) uintptr
代码如下:
package main
import ("fmt""unsafe"
)
type Person struct {name stringage intgender bool
}
func main() {john := Person{"John", 30, true}pp := unsafe.Pointer(&john) // 结构体的起始地址pname := (*string)(unsafe.Pointer(uintptr(pp) + unsafe.Offsetof(john.name))) // 属性name的起始地址,转换为*string类型page := (*int)(unsafe.Pointer(uintptr(pp) + unsafe.Offsetof(john.age))) // 属性age的起始地址,转换为*int类型pgender := (*bool)(unsafe.Pointer(uintptr(pp) + unsafe.Offsetof(john.gender))) // 属性gender的起始地址,转换为*bool类型// 进行赋值*pname = "Alice"*page = 28*pgender = falsefmt.Println(john) // {Alice 28 false}
}
实验结果如下:
go uintptr unsafe Pointer offset() 的使用相关推荐
- uintptr和unsafe.Pointer的区别
unsafe.Pointer其实就是类似C的void *,在golang中是用于各种指针相互转换的桥梁.uintptr是golang的内置类型,是能存储指针的整型,uintptr的底层类型是int,它 ...
- Golang unsafe.Pointer指针
相较于 C 而言,Go 语言在设计时为了使用安全给指针在类型和运算上增加了限制,这让Go程序员既可以享受指针带来的便利,又避免了指针的危险性.除了常规的指针外,Go 语言在 unsafe 包里其实还通 ...
- Go unsafe Pointer
Go unsafe Pointer Go被设计为一种强类型的静态语言,强类型意味着类型一旦确定就无法更改,静态意味着类型检查在运行前就做了. 指针类型转换 为了安全考虑,两个不同类型的指针不能相互转换 ...
- Go 指针 unsafe.Pointer
Go语言是个强类型语言.也就是说Go对类型要求严格,不同类型不能进行赋值操作.指针也是具有明确类型的对象,进行严格类型检查.下面的代码会产生编译错误 : package main import (&q ...
- 深度解密Go语言之unsafe
上一篇文章我们详细分析了 map 的底层实现,如果你也跟着阅读了源码,那一定对 unsafe.Pointer 不陌生,map 对 key 进行定位的时候,大量使用. unsafe.Pointer 位于 ...
- go源码阅读笔记(unsafe)
go源码阅读笔记(unsafe) unsafe 包主要是可以使得用户绕过go的类型规范检查,能够对指针以及其指向的区域进行读写操作. package mathimport "unsafe&q ...
- Go 学习笔记(74)— Go 标准库之 unsafe
Go 语言自带的 unsafe 包的高级用法, 顾名思义,unsafe 是不安全的.Go 将其定义为这个包名,也是为了让我们尽可能地不使用它.不过虽然不安全,它也有优势,那就是可以绕过 Go 的内存安 ...
- runtime error: invalid memory address or nil pointer dereference
runtime error: invalid memory address or nil pointer dereference 解决方法: tcallback((unsigned char*)pac ...
- Golang: unsafe包的使用
1. golang各类型占空间字节数 package mainimport ("fmt""unsafe" )var tByte byte var tRune r ...
最新文章
- 2020 新兴技术炒作周期曲线:这 5 个趋势值得注意
- 关于助动词和过去分词的一点见解
- Web Service 学习笔记(2)
- Java基础 之软引用、弱引用、虚引用
- 段落排版--行间距, 行高(line-height)
- python模块:JSON模块
- JavaScript对象学习笔记
- Hello Quartz (第二部分)
- python开发环境一般用哪个快递_基于Python的常用快递sdk调用代码实例
- GlobalMapper20使用控制点对地形数据(高程数据)进行高程纠正(高程拟合/纠偏/配准)
- 软件测试:系统测试之因果图方法
- 项目时间进度计划与项目进度控制
- 24点递归实现(c语言)
- Python猴子补丁
- 深度学习Hello World --- 手写体识别 实战
- cfree 上面工具栏消失解决办法(不用重下!!!!!)
- 【2】输入俩个数m,n,字符串st1为1-m组成,输出字符串的倒数第n个字符
- Word产品需求文档,已经过时了
- 虚拟摄像头(拉rtsp流或桌面作为图像源)
- kubernetes节点NotReady