ポインタが分からない③
やっと分かってきた感
まだポインタのことで悩んでいたのかと言われても仕方ないが、以下の記事を読んでいてやっと分かってきた感じがする。
C/C++は永久に不滅です! - Part4 誰もがつまずくポインタを完璧理解:ITpro
この中の「図3●int *p =&a;を実行したときのメモリーの状態」という図を見て、気づいたことが、
p := 10 q := &p *q = 7
これがコンパイルエラーにならないんじゃないかということ。
実際ならなくて、3行めの文によってqの大元の変数pに7という別の数を代入したことになる。
間接参照演算子「*」を左辺に持ってきてはいけないと思いこんでいたことに気づく。
サンプルコード
package main import "fmt" type Point struct { x int y int } func main() { p := Point{0, 0} q := &p r := *q // rにはqの大元の変数p(の値)を保持しておく。rとpは別のメモリが割り当てられる。 fmt.Printf("p: %p q: %p r:%p\n", &p, q, &r) // p: 0xc82000a320 q: 0xc82000a320 r:0xc82000a330 p.x = 8 fmt.Println(p, q, r) // {3 10} &{3 10} {0 0} // ここで、qの大元の変数に新しいPointのオブジェクトを入れる。 // -> pに代入しているのと同じで、なおかつ、rには影響しない。 *q = Point{3, 3} // 左辺に間接参照演算子「*」を持ってこられる点に驚き。 p.y += 7 fmt.Println(p, q, r) // {3 10} &{3 10} {0 0} }
わかったこと
- 変数には、(普通の)変数とポインタ変数の2種類ある。
- 変数に変数を代入した場合は別々のメモリが割り振られる。 -> r = p としたら、pとrは別物。但し値がコピーされる。
- ポインタ変数を作って変数のアドレスを代入すると、同じものを指す。 -> q = &p としたら、pとqは同じもの。
- 間接参照演算子「*」を使うと、ポインタ変数の大元の変数にアクセスできる。これは参照も代入も可能。