2 つのローカル変数を宣言して初期化する関数があるとします。デフォルトでは、ストレージ期間はauto
です。次に、この関数は 2 番目の関数を呼び出し、この関数にこれら 2 つのローカル変数のアドレスを渡します。この 2 番目の関数は、これらのポインターを安全に使用できますか?
その説明を補足するための簡単なプログラムの例:
#include <stdio.h>
int adder(int *a, int *b)
{
return *a + *b;
}
int main()
{
auto int a = 5; // `auto' is redundant; included for clarity
auto int b = 3;
// adder() gets the addresses of two auto variables! is this an issue?
int result = adder(&a, &b);
printf("5 + 3 = %d\n", result);
return 0;
}
このプログラムは期待どおりに動作し、印刷し5 + 3 = 8
ます。
通常、C について質問があるときは標準に目を向けますが、これも例外ではありませんでした。具体的には、ISO/IEC 9899の §6.2.4 を確認しました。そこには、部分的に次のように書かれています。
4 識別子がリンケージおよびストレージ クラス指定子なしで宣言されているオブジェクトには、
static
自動ストレージ期間があります。5 可変長配列型を持たないオブジェクトの場合、その有効期間は、関連付けられているブロックへのエントリから、そのブロックの実行が何らかの形で終了するまで延長されます。(囲まれたブロックに入るか、関数を呼び出すと、現在のブロックの実行が中断されますが、終了しません。) ブロックに再帰的に入ると、オブジェクトの新しいインスタンスが毎回作成されます。オブジェクトの初期値は不定です。オブジェクトの初期化が指定されている場合、ブロックの実行で宣言に到達するたびに実行されます。そうしないと、宣言に到達するたびに値が不確定になります。
これを読んで、私は次の点を推論します。
変数
a
には、キーワードを使用して明示的に作成したb
storage durationがあります。auto
auto
関数の呼び出しは、
adder()
上記の部分引用の節 5 の括弧に対応します。つまり、adder()
関数に入ると、現在のブロック (つまり ) の実行が「一時停止しますが、終了しません」main()
。main()
ブロックは決して「終了」していないため、 および のストレージはa
保証b
されます。&a
したがって、アドレスおよびを使用してそれらにアクセスすることは、 の&b
内部であってもadder()
安全です。
私の質問は次のとおりです。私はこれで正しいですか?それとも、「運が良かった」だけで、たまたま上書きされていないメモリ位置にアクセスしているだけなのでしょうか?
PS Google でも SO の検索でも、この質問に対する正確な回答を見つけることができませんでした。可能であれば、これを重複としてマークしてください。削除します。