🧩 関数とスコープ
🎯 関数呼び出しでスタックフレームが積まれ、戻るときに降ろされる流れを説明できる
関数を呼ぶと、なぜ元の場所に戻ってこられるのでしょうか。しかも、呼ばれた側のローカル変数はどこに置かれているのでしょうか。その舞台裏がコールスタックです。
食堂のお盆を想像してください。新しいお盆は必ずいちばん上に積み、取るときもいちばん上から取ります。関数の呼び出しもこれと同じ規則で動きます。
return する → いちばん上のフレームを丸ごと捨て、戻り先へジャンプする#include <stdio.h>
int square(int x)
{
int r = x * x;
return r;
}
int calc(int a)
{
int s = square(a);
return s + 1;
}
int main(void)
{
int n = 3;
int ans = calc(n);
printf("%d\n", ans);
return 0;
}main → calc → square と3段積まれ、square が終わると上から順に降りてきます。降ろされたフレームの中身(x や r)は、そこで消えます。前のトピックの「ブロックを抜けると変数が消える」は、この仕組みの結果だったわけです。
下のビジュアライザで、フレームが積まれて降りる様子を1行ずつ確かめてください。
🧪 ここはメモリの中身を1ステップずつ追う「メモリビジュアライザ」の場面です(アプリ本体で動きます)。
フレームに入っている「帰り道」
フレームの中でいちばん地味で、いちばん重要なのが戻り先の住所です。calc の中で square を呼ぶとき、「終わったら calc の続きに帰る」という情報も一緒に積まれます。これがあるから、同じ square を100か所から呼んでも、それぞれ正しい場所へ帰れます。関数が「行って帰ってこられる」のは、この一枚のメモのおかげです。
積みすぎると崩れる
#include <stdio.h>
void dig(int n)
{
int buf[1000]; // 呼ぶたびに約4KBを積む
printf("%d\n", n);
dig(n + 1); // 止まらない!
}
int main(void)
{
dig(1);
return 0;
}このプログラムは数千回から数万回で異常終了します(回数は環境によって変わります)。return に到達しないので、フレームは積まれる一方で降りてきません。積む場所には上限があるため、いつか限界に達します。
罠・注意
int buf[1000000]; のような巨大なローカル配列です。まとめ: 呼べば積み、戻れば降ろす。コールスタックはCの実行の背骨で、スコープ・寿命・再帰・ポインタの事故まで、すべてここに繋がります。
関数が呼び出されるたびに積み上がっていく、実行中の関数の記録のこと。関数から戻ると一番上から取り除かれる、積み木のような仕組み。スタックオーバーフローは、この積み重ねが限界を超えたときに起きる。
もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。