Go中的指针算法

22 pointers go pointer-arithmetic

考虑到你可以(不能想出一个很棒的方法,但是)操作Go中的指针,是否有可能像在C中那样执行指针运算,比如迭代一个数组?我知道这些日子循环对于那种事情来说很好但是我只是好奇它是否可能.

Tim*_*per 34

不是.来自Go常见问题:

为什么没有指针算术?

安全.如果没有指针算法,就有可能创建一种永远不会导致错误成功的非法地址的语言.编译器和硬件技术已经发展到使用数组索引的循环可以像使用指针算法的循环一样高效的程度.此外,缺少指针算法可以简化垃圾收集器的实现.

话虽这么说,你可以通过使用unsafe包来解决这个问题,但不要:

package main

import "fmt"
import "unsafe"

func main() {
    vals := []int{10, 20, 30, 40}
    start := unsafe.Pointer(&vals[0])
    size := unsafe.Sizeof(int(0))
    for i := 0; i < len(vals); i++ {
        item := *(*int)(unsafe.Pointer(uintptr(start) + size*uintptr(i)))
        fmt.Println(item)
    }
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/QCHEQqy6Lg

  • 我不明白为什么// go:nosplit会以某种方式在这里发挥作用.// go:nosplit注释告诉编译器在进入函数时不检查堆栈溢出.这有副作用,垃圾收集器在进入函数时不会运行.但是这些指针正在函数内部被操纵,并且:nosplit不会影响它.记录何时在unsafe.Pointer和uintptr之间进行转换是安全的问题是https://golang.org/issue/8994. (6认同)

Rod*_*igo 5

从 Go 1.17 开始,我们现在有了unsafe.Add,这使得它变得更容易一些:

package main

import (
    "unsafe"
)

func main() {
    vals := []int{10, 20, 30, 40}

    ptrStart := unsafe.Pointer(&vals[0])
    itemSize := unsafe.Sizeof(vals[0])

    for i := 0; i < len(vals); i++ {
        item := *(*int)(unsafe.Add(ptrStart, uintptr(i)*itemSize))
        println(item)
    }
}
Run Code Online (Sandbox Code Playgroud)

游乐场