ポインタの復習

この章でやること

入門の第7章では、ポインタを「入口だけ」と断って終えました。& で番地を取り出し、* で指す先を読み書きし、関数に番地を渡すと呼び出し元を書き換えられる、というところまでです。この中級コースは、その先を全部扱います。ポインタを 1 つ進めると何が起きるのか、配列とポインタはなぜ混ざって見えるのか、必要な分だけメモリを自分で借りるとはどういうことか、という順に進みます。

最初の回は足場の確認です。新しい道具は出てきません。ただ、ここから先はポインタが常時登場するので、&* を止まらずに読み書きできる状態にしておきます。

& は番地を取り出す

変数はメモリのどこかに置かれています。その置き場所の先頭番号を取り出すのが & です。

int tanaka = 80; int *p = &tanaka; /* tanaka の番地を p に入れる */

int *p は「p は int を指すポインタです」と読みます。ポインタが持っているのは番地であって、点数そのものではありません。

* は指す先を見る

*p と書くと、p が持っている番地の先を見ます。これを 間接参照 と呼びます。

printf("%d\n", *p); /* 80 */ *p = 85; /* tanaka が 85 になる */ printf("%d\n", tanaka);

*p は読むだけの記号ではありません。代入の左辺にも置けます。tanaka という名札を一度も書かずに tanaka を書き換えられる、というのがポインタの本質でした。

宣言のときの * と、使うときの * は見た目が同じで別物です。宣言の * は「これはポインタです」という印、使うときの * は「指す先を見ろ」という命令です。

関数に番地を渡す

C の引数は値渡しだけです。点数をそのまま渡すと写しが届くので、関数の中で書き換えても呼び出し元には戻りません。番地を渡せば、届いた番地の先を触れるので、呼び出し元そのものを書き換えられます。

void add_bonus(int *score, int bonus) { *score += bonus; }

*score += bonus; は「score が指している先に bonus を足す」です。score += bonus; と書くとポインタのほうを動かしてしまい、まったく別の意味になります。この違いは次回のポインタ演算そのものなので、いまは「* を忘れると意味が変わる」とだけ押さえておいてください。

どこも指していないポインタ

int *p; と宣言しただけのポインタには、ごみの番地が入っています。そのまま *p を触ると関係のない場所を壊すので、行き先が決まっていないうちは int *p = NULL; と書いておきます。NULL は「有効な番地ではない」と決められた値で、使う前に if (p != NULL) で確かめられます。この習慣は、動的メモリに入る第2章から本当に効いてきます。

では、2 人分の点数を読み込んで、ポインタ越しにボーナスを足してみましょう。

要件

  1. 田中さんの点数を指すポインタ p を作り、*p で最初の点数を表示する
  2. void add_bonus(int *score, int bonus) を完成させる
  3. add_bonus を使って 2 人に 5 点ずつ加える
  4. 「田中の点数は80点です」「鈴木の点数は85点です」の形で表示する

入出力例

main("80 85") → "ボーナス前の田中の点数は80点です 田中の点数は85点です 鈴木の点数は90点です" main("72", "64") → "ボーナス前の田中の点数は72点です 田中の点数は77点です 鈴木の点数は69点です" main("95 100") → "ボーナス前の田中の点数は95点です 田中の点数は100点です 鈴木の点数は105点です"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.c
学習モード

メモ

ポインタの復習

⌘S で保存