首页 > 解决方案 > 使用指针算法访问数组元素

问题描述

这是理解 golang 中内存寻址的唯一做法

当我将位添加到地址时,我想访问具有地址 byte的数组元素,必须打印,它打印882008

x := [15]byte{254, 200, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}

地址 := &x[1]

unsafePointer := unsafe.Pointer(address)
fmt.Println(*(*uint8)(unsafe.Pointer(uintptr(unsafePointer)))) // ->254
fmt.Println(*(*uint8)(unsafe.Pointer(uintptr(unsafePointer)+8))) // ->8

标签: gounsafe

解决方案


你做的算术uintptr(unsafePointer)是以字节为单位的,而不是位。

无论如何,从 Go 1.17 开始,您可以使用unsafe.Add指针算术:

函数 Add 将 len 添加到 ptr 并返回更新后的指针 Pointer(uintptr(ptr) + uintptr(len))。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    x := [15]byte{254, 200, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
    address := &x[0]
    unsafePointer := unsafe.Pointer(address)
    fmt.Println(*(*uint8)(unsafePointer))                // 254
    fmt.Println(*(*uint8)(unsafe.Add(unsafePointer, 1))) // 200
    fmt.Println(*(*uint8)(unsafe.Add(unsafePointer, 2))) // 2
}

游乐场: https: //play.golang.org/p/FS7GFN-P_Ez

为了清楚起见,len您应该传递给unsafe.Add的是元素的大小(以字节为单位),您可以使用unsafe.Sizeof. 例如:

package main

import (
    "fmt"
    "unsafe"
)

type Foo struct { 
    Val int
}

func main() {
    x := [...]Foo{newFoo(254), newFoo(200), newFoo(2)}
    address := &x[0]
    unsafePointer := unsafe.Pointer(address)
    fmt.Println(*(*Foo)(unsafePointer))                                     // {254}
    fmt.Println(*(*Foo)(unsafe.Add(unsafePointer, unsafe.Sizeof(Foo{}))))   // {200}
    fmt.Println(*(*Foo)(unsafe.Add(unsafePointer, unsafe.Sizeof(Foo{})*2))) // {2}
}

func newFoo(x int) Foo {
    return Foo{x}
}

在您的示例中,添加无类型常量有效,因为数组元素是字节。


推荐阅读