関数はおそらく5を出力しますが、これは絶対に行わないでください。あなたのプログラムはあなたのリターンのポインタが指す場所をもはや所有していないので(言い換えれば、あなたのプログラムはもはや所有していないi
)、それは未定義の振る舞いです。
基本的に、関数が呼び出されるたびに、新しいスタックフレームに対応するためにスタックポインタが押し下げられます。関数呼び出しが終了すると、スタックポインタがバックアップされます。これは、別の関数が呼び出された場合、前の関数呼び出しと同じスタックスペースと重複することを意味します。
これをもう少しわかりやすく説明するために、次のことを考慮してください。
int main()
{
int *p;
p=func();
printf("%d\n",*p);
func2();
printf("%d\n",*p);
return 0;
}
int *func()
{
int i;
i=5;
return &i;
}
void func2()
{
int i = 1;
}
出力が51になる可能性はかなりあります。これは、2番目の呼び出しが同じスタックスペースを再利用するためです。
(上記のコードスニペットはひどいことに注意してください-そのようなことは絶対にしないでください-未定義の動作であり、実装に大きく依存します。)
質問に直接答えるには:
iのスコープはfunc()で終了しますが、iのアドレスを返すので、main()でアクセスしてprint5を実行できますか?
いいえ、できますが、すべきではありません。これがCの美しさです。コンパイラ/OSなどによっては、5を出力する場合もあれば、ランダムなガレージを出力する場合もあります。
そうでない場合、なぜですか?コンパイラはそのアドレス空間にガベージ値を入れますか(これは行われていないと思います)。
ローカル変数に使用されたスペースは再利用されます。答えの前半は、うまくいけば、これがどのように機能するかを示しています。(まあ、それが通常どのように機能するか。)
変数のスコープが終了するということは、実際にはどういう意味ですか?また、スコープが終了すると、iに割り当てられたメモリは解放されますか?
スタックベースのメモリ割り当ては、舞台裏で行われていることです。