为了账号安全,请及时绑定邮箱和手机立即绑定

将结构转换为字节片的特定地址

将结构转换为字节片的特定地址

Go
皈依舞 2022-05-23 16:20:49
为了解析一个巨大的文件而不必为每个结构复制字节,我想将结构直接转换为字节片中的地址。这仅是出于性能原因。我知道我可以使用 binary.Read() 从字节切片制作结构,但据我所知,这将复制字节,这是一件昂贵的事情;因此我想避免在这个用例中使用这种方法。我似乎确实已经转换了结构,因为我确实得到了我期望的结构中的数据。但是,当我更改结构中的值时,它们不会更改结构地址应指向的字节片吗?对我来说重要的是文件(字节切片)反映了我的结构中数据的变化。如何让结构在文件中的相应地址上工作?这是我到目前为止所做的演示:type T struct {    A uint8}func main() {    data := []byte{0xA, 0xB, 0xC}    // Cast bytes to struct    pointer := *(*uint8)(unsafe.Pointer(&data[0]))    fmt.Printf("ptr:\t0x%x\n", pointer)    t2 := *(*T)(unsafe.Pointer(&pointer))    fmt.Printf("T:\t0x%x\n\n", t2.A)    // byte casting to struct ends here    // test    t2.A = 0x0 // I expect this to change for data as well but it does not.    fmt.Println("AFTER CHANGE OF t2.A")    fmt.Printf("data[0]:0x%x\n", data[0])    fmt.Printf("ptr:\t0x%x\n\n", pointer)    fmt.Println("WHY ARE THESE ON DIFFERENT ADDRESSES?")    fmt.Printf("DataAddr: 0x%p\n", data)    fmt.Printf("PtrAddr: 0x%p\n", &pointer)    fmt.Printf("T2Addr: 0x%p\n", &t2)}这打印出来:ptr:    0xaT:      0xaAFTER CHANGE OF t2.A - the original data slice has not been altered.data[0]:0xaptr:    0xaADDRESSESDataAddr: 0x0xc000094010PtrAddr: 0x0xc000094013T2Addr: 0x0xc000094030
查看完整描述

1 回答

?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

您正确地转换了指针,但随后您取消了它的引用,从而生成了一个副本。然后你继续获取副本的地址,转换该指针并再次取消引用它(这会产生另一个副本)。修改任何副本不会对其他副本产生任何影响。


所以简单地不要取消引用指针(最终我们只是修改将在同一内存位置的指向值):


data := []byte{0xA, 0xB, 0xC}


// Cast bytes to struct

pointer := (*uint8)(unsafe.Pointer(&data[0]))

fmt.Printf("ptr:\t0x%x\n", *pointer)


t2 := (*T)(unsafe.Pointer(pointer))

fmt.Printf("T:\t0x%x\n\n", t2.A)

// byte casting to struct ends here


// test

t2.A = 0x0 // This will also change data


fmt.Println("AFTER CHANGE OF t2.A")

fmt.Printf("data[0]:0x%x\n", data[0])

fmt.Printf("ptr:\t0x%x\n\n", *pointer)


fmt.Println("ADDRESSES ARE ALL THE SAME:")

fmt.Printf("DataAddr: 0x%p\n", &data[0])

fmt.Printf("PtrAddr: 0x%p\n", pointer)

fmt.Printf("T2Addr: 0x%p\n", t2)

输出(在Go Playground上试试):


ptr:    0xa

T:  0xa


AFTER CHANGE OF t2.A

data[0]:0x0

ptr:    0x0


ADDRESSES ARE ALL THE SAME:

DataAddr: 0x0x40e020

PtrAddr: 0x0x40e020

T2Addr: 0x0x40e020


查看完整回答
反对 回复 2022-05-23
  • 1 回答
  • 0 关注
  • 130 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号