アドレスとは
変数はメモリのどこかに置かれている
第2章から、点数を int score = 80; のように変数に入れてきました。ではその 80 は、どこにあるのでしょうか。答えはメモリです。プログラムを実行すると、コンピュータはメモリの中から int 1 個分の場所を確保して、そこに 80 を書き込みます。
メモリは、番号の振られた巨大なロッカーの列だと考えてください。この番号のことを アドレス、日本語では番地と呼びます。変数名 score は、人間が読みやすいように付けた名札にすぎません。コンパイラはその名札を「何番地のロッカーか」に翻訳してから機械語を出しています。
& で番地を取り出す
変数の前に & を付けると、その変数が置かれている番地が取り出せます。この & を アドレス演算子 と呼びます。
int score = 80;
printf("%p\n", (void *)&score); // 番地が表示される%p は番地を表示するための書式指定子です。ただし、ここで出た数字を覚えても意味がありません。表示される番地は実行するたびに変わる からです。OS はプログラムを起動するたびに、その時点で空いている場所を割り当てます。同じプログラムを 2 回動かして違う数字が出ても、故障ではなく正常な動きです。
この講座の課題でも、番地そのものを表示させることはしません。答え合わせのしようがないからです。
大事なのは番地どうしの関係
代わりに確かめられるのは、番地どうしの関係です。
int score1 = 80;
int score2 = 80;
if (&score1 != &score2) {
printf("別の場所にあります\n");
}score1 と score2 は値がどちらも 80 ですが、別々の変数なので必ず別の場所に置かれます。だから score1 を書き換えても score2 は巻き添えを食いません。当たり前に感じるこの性質は、2 つが違う番地を持っているからこそ成り立っています。
番地は先頭のロッカー番号
ロッカー 1 個は 1 バイト、つまり 8 ビット分です。int は多くの環境で 4 バイトなので、ロッカーを 4 個続けて使います。sizeof(int) と書けば、その環境で何バイトかを確かめられます。
では &score はその 4 個のうちどれを指すのかというと、先頭 です。番地だけでは「そこから何バイトを、どう解釈して読むか」が決まらないので、番地と型の 2 つがそろって初めて値が読めます。この考え方が、次回のポインタでそのまま効いてきます。
では、値が同じ 2 つの点数が別の場所に置かれていることを、プログラムで確かめてみましょう。
要件
- score1 と score2 にどちらも 80 を入れる
- それぞれの値を 「score1の値は80点です」 の形で表示する
- & で取り出した番地を比べ、違うなら 「2つは別の番地にあります」 と表示する
- int が何バイトかを 「intは4バイトです」 の形で表示する
入出力例
main("") → "score1の値は80点です
score2の値は80点です
2つは別の番地にあります
intは4バイトです"