Go中的指针算术

huangapple go评论98阅读模式
英文:

Pointer arithmetic in Go

问题

在Go语言中,可以(无法想到一个很好的表达方式,但是)操作指针,那么是否可以像在C语言中那样执行指针算术运算,比如用于遍历数组?我知道现在使用循环来完成这种操作已经很常见了,但我只是好奇是否在Go语言中也可以这样做。

英文:

Considering you can (can't think of a great way to put it, but) manipulate pointers in Go, is it possible to perform pointer arithmetic like you would in C, say for iterating over an array? I know loops are just fine for that kind of things these days but I'm just curious if it's possible.

答案1

得分: 60

根据Go FAQ中的说明,为了安全起见,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)
    }
}

你可以在这里运行这段代码。

英文:

No. From the Go FAQ:

> ### Why is there no pointer arithmetic?
>
> Safety. Without pointer arithmetic it's possible to create a language that can never derive an illegal address that succeeds incorrectly. Compiler and hardware technology have advanced to the point where a loop using array indices can be as efficient as a loop using pointer arithmetic. Also, the lack of pointer arithmetic can simplify the implementation of the garbage collector.

That being said, you can get around this by using the unsafe package, but just don't:

package main

import &quot;fmt&quot;
import &quot;unsafe&quot;

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

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

答案2

得分: 4

截至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)
    }
}

Playground

英文:

As of Go 1.17, we now have unsafe.Add, which makes it a little easier:

package main

import (
    &quot;unsafe&quot;
)

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

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

    for i := 0; i &lt; len(vals); i++ {
        item := *(*int)(unsafe.Add(ptrStart, uintptr(i)*itemSize))
        println(item)
    }
}

Playground.

huangapple
  • 本文由 发表于 2015年9月22日 01:13:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/32700999.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定