首页 > 解决方案 > 如何理解 uintptr 和 struct 之间的关系?

问题描述

我已经学习了如下代码

func str2bytes(s string) []byte {
    x := (*[2]uintptr)(unsafe.Pointer(&s))
    h := [3]uintptr{x[0], x[1], x[1]}
    return *(*[]byte)(unsafe.Pointer(&h))
}

此功能是更改string[]byte无阶段复制数据。
我尝试将 num 转换为 reverseNum

type Num struct {
    name  int8
    value int8
}

type ReverseNum struct {
    value int8
    name  int8
}
func main() {
    n := Num{100, 10}
    z := (*[2]uintptr)(unsafe.Pointer(&n))
    h := [2]uintptr{z[1], z[0]}
    fmt.Println(*(*ReverseNum)(unsafe.Pointer(&h))) // print result is {0, 0}
}

这段代码没有得到我想要的结果。谁能告诉我

标签: go

解决方案


这太复杂了。
更简单的

package main

import (
    "fmt"
    "unsafe"
)

type Num struct {
    name  int8
    value int8
}

type ReverseNum struct {
    value int8
    name  int8
}

func main() {
    n := Num{name: 42, value: 12}

    p := (*ReverseNum)(unsafe.Pointer(&n))

    fmt.Println(p.value, p.name)
}

输出“42, 12”。


但真正的问题是,你到底为什么要使用这种诡计而不是复制两个在运行任何明智的 CPU 围棋程序上立即完成的怪异字节?

您的方法的另一个问题是,IIUC 在Go 语言规范中没有任何内容保证具有看似相同字段的两种类型必须具有相同的内存布局。我相信他们应该在大多数实施中,但我认为他们不需要这样做。

还要考虑看似无害的事情,例如您的数据类型中还有一个额外的字段(甚至类型!)可能会对这些类型的变量的内存布局产生有趣的影响,因此假设您可能重新解释Go 的内存可能是完全危险的变你想要的方式。struct{}


推荐阅读