// C(/C++)言語のポインタとアドレスの話・初心者向け ---------------------------------------------------------------
//
// 「引数の話」の中で、「実引数」と「仮引数」は別物という話をしたけど、この
//
// 「別物って、何?どういう事?」。 これがテーマ。
//
void function_1(int a) // 仮引数の a
{
a += 10;
printf("function にて → %d \n", a);
}
void proc_A()
{
int a = 123;
function_1(a); // 実引数の a
printf("親の関数 にて → %d \n", a);
}
//
// ↑上の2つの「a」。これの正体を暴いてみる↓
//
void function_2(int a)
{
// ↓コピー先 = &変数 は「その変数が置かれているメモリのアドレス」を取得する
printf("仮引数のアドレス → %X \n", &a);
}
void proc_B()
{
int a = 123;
function_2(a);
printf("実引数のアドレス → %X \n", &a);
}
//
// ↑表示される両者の「アドレス」。先に変数は「メモリ上のどこかに名前を付けただけ」って話をしたが、
// これ。「コピーされて渡されてるので、当然別のアドレスが表示される」
//
// int a1 = 123;
// int a2 = a1;
// a2 += 10;
// これなら当然 a1 が変わる事は無いってのと、同じ。で、このアドレス。
//
// 全てはこの「アドレス」に、本当の本物の値が格納されていると(とりあえず)思っておけばおk。
//
// で、ポインタ。ポインタ変数は、
void proc_C()
{
int a = 10; // ← メモリ上の a と名前が付けられたどこかに 「符号あり整数値を」格納している。
int *p = &a; // ← メモリ上の p と名前が付けられたどこかに 「符号なしアドレス整数値を」格納している。
printf("a の値 = %d\n", a);
printf("p の値 = %X\n", p);
// ↑この時、上の例で言うと、p は 「変数 a のアドレスを受け取っている」。
//
// ポインタ変数は、特にこの「アドレスを受け取って」その「アドレス整数値を計算したり」
// ↓ pの持っているアドレス整数に1を足す = 1つ先のアドレスを指す
p += 1;
printf("p の値その2 = %X\n", p);
// ↓1つ前のアドレスに戻す=元通りのアドレス整数値
p -= 1;
// 「そのアドレスの内容を触ったり」出来る。
printf("pのアドレスが指す先にある値 = a と同じ … %d\n", *p);
}
//
// で、ここで大事な事。
// >↓ pの持っているアドレス整数に1を足す = 1つ先のアドレスを指す
//
// Q)1つ先のアドレスって、A0000000 に対して、A0000001 でいいの?
// A)違う
//
// int *p を p += 1 すると、「int のサイズ分移動した先のアドレス」を指す。
//
// ※具体的にサイズがいくつか?については正確には sizeof(int) のようにして求めるが、
// 32bitのWindowsだと、大抵32bit = 4バイト。単純に sizeof(型) 分移動するとだけ覚えておけばおk
//
// という事は、当然「別の型 *p = &変数」のようにしたら、そのポインタ変数が持つアドレスの1つ先は…
// 具体例↓
//
void proc_D()
{
typedef struct { int a; int b; } DATA;
DATA s = {10, 20};
DATA *p = &s;
printf("とある構造体のサイズ(byte) = %X\n", sizeof(DATA));
printf("とある構造体のアドレス+0 = %X\n", p);
p += 1;
printf("とある構造体のアドレス+1 = %X\n", p);
}
//
// ↑ sizeof(DATA) 分、アドレスが移動しているはず
//
//
// この「アドレスの先にある値」という考え方が出来るようになったり、
// 「そのアドレス整数値そのもの」を扱える「ポインタ(型変数)」という存在がわかると、
//
// ・「配列変数」
// ・「複数の値を返す関数」
// ・などいろいろ
//
// が見えてくる。とりあえずここまで
//
#define HR() printf("\n-----------------------------------------------------\n\n")
int main()
{
proc_A(); HR();
proc_B(); HR();
proc_C(); HR();
proc_D(); HR();
return 0;
}