转投go系列-指针操作与运算

静态语言与动态脚本语言有意思的是,可以直接操作指针,移动指针操作变量。

我们都学过C++,当时也被指针操作所困扰。go确实不能直接操作指针,但是go提供了一个unsafe包可以这么样的操作。

package unsafe

type ArbitraryType int
type IntegerType int
type Pointer *ArbitraryType

func Sizeof(x ArbitraryType) uintptr
func Offsetof(x ArbitraryType) uintptr
func Alignof(x ArbitraryType) uintptr

//go1.17
func Add(ptr Pointer, len IntegerType) Pointer  
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType 
  • Sizeof 返回变量在内存中占用的字节数
  • Offsetof 返回变量指定属性的偏移量,这个函数是接收一个struct类型变量的属性当作参数。
  • Alignof 返回当前变量对于当前struct类型的偏移量,考虑内存对齐
  • Add (1.17新加入)指针运算,加上一个偏移量
  • Slice (1.17新加入)返回一个切片

这里面还提到2个类型,uintptr和unsafe.Pointer
他俩的区别就是:

  • unsafe.Pointer仅仅是通用指针类型,用于转换不同类型指针;
  • uintptr仅仅是用于指针运算的;

转化过程如下:

普通指针->unsafe.Pointer->uintptr进行加减运算->unsafe.Pointer->普通指针

那么我也尝试了用代码体验了一番:

package unsafe_cmd

import (
	"fmt"
	"reflect"
	"unsafe"
)

type MyT struct {
	i32 int32
	i64 int64
}

func (myT *MyT) GetI32() {
	fmt.Printf("value: %v", myT.i32)
}

func (myT *MyT) GetI64() {
	fmt.Printf("value: %v", myT.i64)
}

func UnsafeMain() {
	my := &MyT{}
	i32 := (*int32)(unsafe.Pointer(my))
	*i32 = 187

	i64 := (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(my)) + uintptr(4)))
	i644 := (*int64)(unsafe.Add(unsafe.Pointer(my), 8))

	fmt.Println(unsafe.Offsetof(my.i32))
	fmt.Println(unsafe.Offsetof(my.i64))
	fmt.Println(reflect.ValueOf(i644))
	fmt.Println(reflect.ValueOf(&my.i32))
	fmt.Println(reflect.ValueOf(&my.i64))
	*i64 = 100000
	my.GetI32()
	fmt.Println()
	my.GetI64()
	fmt.Println()

	*i644 = 100001
	my.GetI64()
	fmt.Println()
}

打印结果:

$ go run main.go
0
8
0x14000096018
0x14000096010
0x14000096018
value: 187
value: 0
value: 100001

我先定义了一个struct,里面两个变量,一个int32,一个int64。
我先初始化了对象为myT,然后通过pointer对象的指针,获取到第一个属性的指针,赋值为187

然后用第一个属性的指针做了偏移量相加的运算,这里我加了4,然后赋值100000,原以为可以打印出对应值。结果打印的是0。这里的主要原因是因为内存对其

后来我用Offsetof再次确认了一下,果然+4是错的。
于是我又换成+8(看代码我用的1.17的新特性,Add方法和直接±是一样的),赋值成功

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值