ポインタとは?
ポインタ (英: pointer) とは、あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、それを参照する(指し示す)ものである。有名な例としては Pascal のポインタが挙げられる。
wikipedia参照
なるほど〜、だからポインタ変数からアドレスを取得できて、普通の変数からでも&を使うことでアドレス取得できるんだね!
しかもポインタ変数は*を使って、参照先のリテラルも取得できるんだ!
素敵ーー!!
超便利ーーーーーー!!
ってなるかぼけーーーーーーーーーー!!
とお怒りのみなさんのお気持ちすごくわかります。
ということで自分なりにまとめて見たいと思います。
package main
import (
"fmt"
)
func main() {
// int型のポインタ変数
var p *int
// 普通のint型変数
var n int = 1000
// &(アドレス演算子)を使って、nのアドレスを代入
p = &n
//ポインタ変数にはアドレスが格納されているので、アドレスがそのまま出力
fmt.Println("pの値:", p)
// *を使って、ポインタの中身(リテラル)を)取得することができる
fmt.Println("pの中身:", *p)
//当然int型のリテラルが表示される
fmt.Println("nの値:", n)
//&を使うことによって、普通のint型の変数でもアドレスを取得することができる
fmt.Println("nのアドレス:", &n)
}
結果はこうなります。
pの値: 0xc420086008
pの中身: 1000
nの値: 1000
nのアドレス: 0xc420086008
注意しなければいけないのは、変数定義で使う*とすでに定義済み変数に対して使う*は全く意味が違うんですねぇ。
自分はこれがわからず、最初混乱していました。
変数定義で利用しているは、ポインタ変数と呼ばれる、メモリの割当先アドレスを格納するための特殊な変数を定義する際に利用されます。
では、定義済み変数で利用するはなんなんでしょうか。
これは、「間接参照演算子」と呼ばれるもので、ポインタ変数自体に代入されている値は16真数のメモリのアドレスなのですが、そのアドレスが指し示すリテラルを取得することができます。
具体滝にはこの部分ですね。
//ポインタ変数にはアドレスが格納されているので、アドレスがそのまま出力
fmt.Println("pの値:", p)
//=> 「pの値: 0xc420086008」と出力する
// *を使って、ポインタの中身(リテラル)を)取得することができる
fmt.Println("pの中身:", *p)
//=>「pの中身: 1000」と出力する
ではもう一つ、&というもう一つ演算子がありますが、これは「アドレス演算子」と呼ばれ、普通のint型の変数は当然int型の整数が値として代入されていますが、&を使うことによってその変数が格納されているメモリ上のアドレスを取得することができます。
具体的には下記
//当然int型のリテラルが表示される
fmt.Println("nの値:", n)
//=> 「nの値: 1000」と出力される
//&を使うことによって、普通のint型の変数でもアドレスを取得することができる
fmt.Println("nのアドレス:", &n)
//=>「nのアドレス: 0xc420086008」と出力される
ということです。最初混乱するかもしれませんが、一つ一つ理解して、慣れてしまえばなんてことないと思うので、怖がらずにポインタ使いましょう!!