Подтвердить что ты не робот

Использование указателя на массив

У меня небольшая игра с языком google Go, и я столкнулся с чем-то, что является довольно простым в C, но, похоже, не рассматривается в документации, которую я видел до сих пор.

Когда я передаю указатель на фрагмент функции, я предположил, что у нас есть способ получить к нему доступ следующим образом:

func conv(x []int, xlen int, h []int, hlen int, y *[]int)

    for i := 0; i<xlen; i++ {
        for j := 0; j<hlen; j++ {
            *y[i+j] += x[i]*h[j]
        }
    }
 }

Но компилятору Go это не нравится:

[email protected]:~/dev$ 8g broke.go
broke.go:8: invalid operation: y[i + j] (index of type *[]int)

Достаточно честный - это было просто предположение. У меня есть довольно простой способ:

func conv(x []int, xlen int, h []int, hlen int, y_ *[]int) {
    y := *y_

    for i := 0; i<xlen; i++ {
        for j := 0; j<hlen; j++ {
            y[i+j] += x[i]*h[j]
        }
    }
}

Но, конечно, лучший способ. Досадно, что поиск в Google для Go не очень полезен, поскольку для большинства поисковых запросов появляются всевозможные C/С++/несвязанные результаты.

4b9b3361

Ответ 1

Документы Google Go сообщают следующее о передаче массивов - говорят, что вы обычно хотите передать срез (вместо указатель):

Обновлено:

Как указано комментарием @Chickencha, срезы массива являются ссылками, поэтому они эффективны для прохождения. Вероятно, вы захотите использовать механизм среза вместо "сырых" указателей.

От Эффективный документ Google http://golang.org/doc/effective_go.html#slices

Срезы являются ссылочными типами,


Оригинальные

Это под заголовком

Интерлюдия о типах

[... snip...] При передаче массива к функции, вы почти всегда хотите объявить формальный параметр ломтик. Когда вы вызываете функцию, берем адрес массива и Go создаст (эффективно) срез ссылку и передать это.

Примечание редактора: это уже не так.

Используя срезы, эту функцию можно написать (из sum.go):

09    func sum(a []int) int {   // returns an int
10        s := 0
11        for i := 0; i < len(a); i++ {
12            s += a[i]
13        }
14        return s
15    }

и вызовите его следующим образом:

19        s := sum(&[3]int{1,2,3})  // a slice of the array is passed to sum    

Возможно, передайте весь массив как срез. Google указывает, что Go работает эффективно с помощью срезов. Это альтернативный ответ на вопрос, но, возможно, это лучший способ.

Ответ 2

Типы с пустым [], такие как []int, на самом деле являются срезами, а не массивами. В Go размер массива является частью типа, поэтому для фактического наличия массива вам нужно иметь что-то вроде [16]int, а указателем на это будет *[16]int. Итак, то, что вы на самом деле делаете, уже использует срезы, а указатель на срез *[]int не нужен, поскольку срезы уже переданы по ссылке.

Также помните, что вы можете легко передать срез, ссылающийся на весь массив с помощью &array (если тип элемента среза совпадает с типом элемента массива). (Не больше.)

Пример:

package main
import "fmt"

func sumPointerToArray(a *[8]int) (sum int) {
    for _, value := range *a { sum += value }
    return
}
func sumSlice (a []int) (sum int) {
    for _, value := range a { sum += value }
    return
}
func main() {
    array := [...]int{ 1, 2, 3, 4, 5, 6, 7, 8 }
    slice := []int{ 1, 2, 3, 4 }
    fmt.Printf("sum arrray via pointer: %d\n", sumPointerToArray(&array))
    fmt.Printf("sum slice: %d\n", sumSlice(slice))
    slice = array[0:]
    fmt.Printf("sum array as slice: %d\n", sumSlice(slice))
}

Изменить: обновлено, чтобы отражать изменения в Go, поскольку это было впервые опубликовано.

Ответ 3

точка с запятой и звездочка добавляются и удаляются.

* y [i + j] + = x [i] * h [j]
  - >
 (* y) [i + j] + = x [i] * h [j];

Ответ 4

Длина является частью типа массива, вы можете получить длину массива с помощью встроенной функции len(). Поэтому вам не нужно передавать аргументы xlen, hlen.

В Go вы можете почти всегда использовать срез при передаче массива в функцию. В этом случае вам не нужны указатели. На самом деле вам не нужно передавать аргумент y. Это способ C для вывода массива.

В стиле Go:

func conv(x, h []int) []int {
    y := make([]int, len(x)+len(h))
    for i, v := range x { 
        for j, u := range h { 
            y[i+j] = v * u 
        }   
    }   
    return y
}

Вызвать функцию:

conv(x[0:], h[0:])

Ответ 5

Здесь работает рабочая программа Go.

package main

import "fmt"

func conv(x, h []int) []int {
    y := make([]int, len(x)+len(h)-1)
    for i := 0; i < len(x); i++ {
        for j := 0; j < len(h); j++ {
            y[i+j] += x[i] * h[j]
        }
    }
    return y
}

func main() {
    x := []int{1, 2}
    h := []int{7, 8, 9}
    y := conv(x, h)
    fmt.Println(len(y), y)
}

Чтобы избежать неправильных догадок, прочитайте документацию Go: Язык программирования Go.