Арифметика указателей в Go

Учитывая, что вы можете (не могу придумать отличный способ выразить это, но) манипулировать указателями в Go, возможно ли выполнять арифметические операции с указателями, как в C, скажем, для перебора массива? Я знаю, что петли в наши дни отлично подходят для таких вещей, но мне просто любопытно, возможно ли это.


person Community    schedule 21.09.2015    source источник


Ответы (1)


Нет. Из часто задаваемых вопросов о 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)
    }
}

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

person Tim Cooper    schedule 21.09.2015
comment
если вы сделаете это, используйте //go:nosplit, иначе вы рискуете испортить состояние gc. - person thwd; 21.09.2015
comment
Я не понимаю, почему //go:nosplit так или иначе будет иметь здесь значение. Комментарий //go:nosplit указывает компилятору не проверять переполнение стека при входе в функцию. Это имеет побочный эффект, заключающийся в том, что сборщик мусора не запускается при входе в функцию. Но эти указатели манипулируются внутри функции, и go:nosplit не повлияет на это. Проблема с документированием безопасного преобразования между unsafe.Pointer и uintptr: golang.org/issue/8994. - person Ian Lance Taylor; 21.10.2015