var x struct {
a bool
b int16
c []int32
}
func main() {
//a := []int32{1 << 9}
//x.c = a
pb := (*[]int8)(unsafe.Pointer(uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.c)))
*pb = []int8{5}
println(x.c[0]) // 5
println(x.c[0]) // 5
fmt.Println(x.c[0]) // 5
fmt.Println(x.c[0]) // 327685 why????????
}
FMT.两次打印相同的 x.c[0],但得到不同的结果。为什么?
使用unsafe
时,您放置了一个int8
片,其底层数组以堆栈形式分配,以代替int32
片。因此,现在您遇到了这样一种情况:运行时认为存在一个int32
值数组,但实际上该数组是int8
值的数组。因此,当fmt.Println
从中读取时,您会读取包含您放置在那里的5
的字节,以及碰巧在那里的任何垃圾。
使用不同的值运行几次,并检查位模式。您将获得一个 LSB 始终为 5 的值。您正在从放置int8
值 5 的内存位置读取int32
。其余三个字节是堆栈剩余值。
如果使用[]int8{5,0,0,0}
初始化切片,则始终会得到 5。
您的代码在go playground
中运行良好。 输出始终为您提供5
.fmt.Println
不会更改x.c[0]
值
法典:
package main
import (
"fmt"
"unsafe"
)
var x struct {
a bool
b int16
c []int32
}
func main() {
//a := []int32{1 << 9}
//x.c = a
pb := (*[]int8)(unsafe.Pointer(uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.c)))
*pb = []int8{5}
println(x.c[0]) // 5
println(x.c[0]) // 5
fmt.Println(x.c[0]) // 5
fmt.Println(x.c[0]) // 327685 why????????
}
输出:
5
5
5
5
链接: https://play.golang.org/p/8l1Vj9of2vR