コース目次 / 第1章
変数はメモリのバイト列 — アドレスとポインタ
printf %pで変数のアドレスを実際に表示し、sizeofでバイト数を確認します。ポインタが「アドレスを値として持つ変数」であることを、&と*の対応で理解します。
まず、変数のアドレスを実際に見ます。下を addr.c として保存します。
#include <stdio.h>
int main(void) {
int x = 42;
int y = 7;
printf("xの値: %d, xのアドレス: %p\n", x, (void*)&x);
printf("yの値: %d, yのアドレス: %p\n", y, (void*)&y);
printf("intのサイズ: %zu バイト\n", sizeof(int));
return 0;
}
gcc -o addr addr.c
./addr
xの値: 42, xのアドレス: 0x7fffe40bbbf0
yの値: 7, yのアドレス: 0x7fffe40bbbf4
intのサイズ: 4 バイト
&x の & は「このアドレスを教えて」という演算子です。%p は、そのアドレスを16進数で表示します。
実行するたびに具体的な数値は変わりますが(OS が毎回メモリの配置を少しずらす、ASLR という仕組みのため)、xとyのアドレスの差が、intのサイズ(4バイト)ぴったりになっているのが分かるはずです。xの後ろに、yが4バイトずれて並んでいる——これが「変数はメモリ上に、決まったバイト数で並んでいる」ということです。
ポインタ — アドレスを、値として持つ変数
ポインタとは、アドレスそのものを値として持つ変数です。& と * は、対になった操作です。
#include <stdio.h>
int main(void) {
int x = 42;
int *p = &x; // p は「xのアドレス」を値として持つ
printf("xの値: %d\n", x);
printf("pの値(xのアドレス): %p\n", (void*)p);
printf("*p(pの指す先の値): %d\n", *p);
*p = 100; // pの指す先(=x)を書き換える
printf("書き換え後のxの値: %d\n", x);
return 0;
}
gcc -o ptr ptr.c && ./ptr
int *p = &x; で、p には x のアドレスが入ります。
*p(アスタリスク)は「pが指す先の値」——つまり x そのものを読みます。
p = 100; とすると、——この対の関係が、ポインタのすべての基本です。p が指す先(x)が書き換わります。& はアドレスを取り、 はアドレスの中身を読み書きする
持ち帰る一言
変数は、アドレスとバイト数の組。ポインタは、そのアドレスを値として持つ変数。 &(アドレスを取る)と *(アドレスの中身を読み書きする)は対の操作。この見方が、次の章の配列、そしてバッファオーバーフローの理解につながります。
こうなっていればOK
卒業まであと4章です。
この章はまだ完了していません。
保存できませんでした(プライベートブラウズ中かもしれません)。この端末に進捗は残りませんが、先へは進めます。