Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于28.2 指针运算代码示例的错误 #42

Open
LeChauvet opened this issue Dec 13, 2020 · 1 comment
Open

关于28.2 指针运算代码示例的错误 #42

LeChauvet opened this issue Dec 13, 2020 · 1 comment

Comments

@LeChauvet
Copy link

但是对于v.j来说,怎么来得到它在内存中的地址呢?其实我们可以获取它相对于v的偏移量(unsafe.Sizeof可以为我们做这个事),但上面的代码并没有这样去实现。各位别急,一步步来。
var j *int64 = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int64(0)))))
其实我们已经知道v是有两个成员的,包括i和j,并且在定义中,i位于j的前面,而i是int32类型,也就是说i占4个字节。所以j是相对于v偏移了4个字节。您可以用uintptr(4)或uintptr(unsafe.Sizeof(int64(0)))来做这个事。unsafe.Sizeof方法用来得到一个值应该占用多少个字节空间。注意这里跟C的用法不一样,C是直接传入类型,而Go 语言是传入值。

以上这一段表述中将uintptr(4)等同于uintptr(unsafe.Sizeof(int64(0))),但其实uintptr(unsafe.Sizeof(int64(0)))==uintptr(8),但是这里var j *int64 = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int64(0)))))是可以正确取到j的值,是因为这里发生了对齐,除了i本身占用4字节,还有4个字节由编译器进行填充,导致unsafe.Offsetof(v.j)和uintptr(unsafe.Sizeof(int64(0)))在64位机器上,值都是8。原文说j是相对于v偏移了4个字节,实际上是错误的,而且也没有说清楚为什么使用uintptr(unsafe.Sizeof(int64(0)))。

@dipelta
Copy link

dipelta commented Dec 17, 2020

同意上面的观点,今天unsafe看了半天,估摸着这里说明好像是有点问题

fmt.Printf("int32所占大小:%d \n", unsafe.Sizeof(int32(0)))  //4
fmt.Printf("int64所占大小:%d \n", unsafe.Sizeof(int64(0)))  //8
fmt.Printf("v内存大小:%d \n", unsafe.Sizeof(*v))  //16

这样说明下,这里自动进行了内存对齐,比较好理解

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants