英文:
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 "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)
}
}
答案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)
}
}
英文:
As of Go 1.17, we now have unsafe.Add
, which makes it a little easier:
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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论