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.Println在相同的x.c [0]中两次,但是得到了不同的结果。为什么?
答案 0 :(得分:2)
使用unsafe
,放置了一个int8
切片,其下层数组在堆栈中分配,代替了int32
切片。因此,现在您遇到一种情况,运行时认为存在一个int32
值数组,但实际上该数组是一个int8
值数组。因此,当fmt.Println
从其中读取时,您将读取包含放置在其中的5
的字节以及碰巧在那里的所有垃圾。
使用不同的值运行几次,然后检查位模式。您将得到一个LSB始终为5的值。您正在从其中放置了int32
值5的存储位置读取int8
。其余三个字节是堆栈剩余值。 / p>
如果您使用[]int8{5,0,0,0}
初始化切片,则总会得到5。
答案 1 :(得分:0)
您的代码在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