LoginSignup
0
0

【Go】swap関数の作成を通してポインタについて学ぶ

Posted at

問題

2つの数字を入れ替えるswap関数を実装します。
swap関数の引数として、2つの数字のメモリアドレスが渡されるものとします。

package main
import "fmt"
func main() {
    num1, num2 := 1, 2
    swap(&num1, &num2)
    fmt.Println(num1, num2) // 2, 1
}

本記事ではポインタそのものに関する解説はしません。
ポインタに関しては以下の記事が参考になります。

誤答

私が最初に考えた答えは以下の通りです。何が誤りなのか考えてみてください。

func swap(a, b *int) (a2, b2 *int) {
    a2, b2 = b, a
    return
}

誤っている点

1. 返り値がある

swap(&num1, &num2)のように呼び出しており返り値を受け取る形式ではないのに、返り値としてx2, y2を返してしまっています。

2. ポインタを使用していない

swap関数の引数として与えられたa, bに格納されているのは、メモリアドレス(値が格納されている場所)のコピーにすぎません。

なのでa2, b2 = b, aとしても、a2, b2b, aの値を代入しているだけで、元の値が変更されるわけではありません。

元の値を変更するにはポインタを使用する必要があります。

簡単な例を挙げます。

package main

import "fmt"

func modify(ptr *int) {
    // *ptrはポインタなので変更される
    *ptr = 100
    // ptrはコピーされた値なので、メモリアドレスは変更されない
    ptr = nil
}

func main() {
    x := 10
    ptr := &x

    fmt.Printf("ptr:%v, *ptr:%v\n", ptr, *ptr) // ptr:0xc0010e010, *ptr:10
    modify(ptr)
    fmt.Printf("ptr:%v, *ptr:%v\n", ptr, *ptr) // ptr:0xc0010e010, *ptr:100
}

正答

以上を踏まえて、正しい答えは以下の通りです。
*a, *b = *b, *aとすることで、コピーされたメモリアドレスではなく、ポインタが指す実際の値を変更できます。

func swap(a, b *int) {
	*a, *b = *b, *a
	return
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0