14

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 可変長配列型を持たないオブジェクトの場合、その有効期間は、関連付けられているブロックへのエントリから、そのブロックの実行が何らかの形で終了するまで延長されます。(囲まれたブロックに入るか、関数を呼び出すと、現在のブロックの実行が中断されますが、終了しません。) ブロックに再帰的に入ると、オブジェクトの新しいインスタンスが毎回作成されます。オブジェクトの初期値は不定です。オブジェクトの初期化が指定されている場合、ブロックの実行で宣言に到達するたびに実行されます。そうしないと、宣言に到達するたびに値が不確定になります。

これを読んで、私は次の点を推論します。

  1. 変数aには、キーワードを使用して明示的に作成したbstorage durationがあります。autoauto

  2. 関数の呼び出しは、adder()上記の部分引用の節 5 の括弧に対応します。つまり、adder()関数に入ると、現在のブロック (つまり ) の実行が「一時停止しますが、終了しません」main()

  3. main()ブロックは決して「終了」していないため、 および のストレージはa保証bされます。&aしたがって、アドレスおよびを使用してそれらにアクセスすることは、 の&b内部であってもadder()安全です。

私の質問は次のとおりです。私はこれで正しいですか?それとも、「運が良かった」だけで、たまたま上書きされていないメモリ位置にアクセスしているだけなのでしょうか?


PS Google でも SO の検索でも、この質問に対する正確な回答を見つけることができませんでした。可能であれば、これを重複としてマークしてください。削除します。

4

4 に答える 4

7

特定の関数呼び出しチェーンに対する推論は正しく、標準の関連部分を読んで引用しました。これは、ローカル変数へのポインターの完全に有効な使用法です。

注意が必要なのは、関数がポインター値を、それ自体の呼び出しよりも長い有効期間を持つ構造体に格納する場合です。foo()と の 2 つの関数を考えますbar()

int *g_ptr;

void bar (int *p) {
    g_ptr = p;
}

void foo () {
    int x = 10;
    bar(&x);
}

int main () {
    foo ();
    /* ...do something with g_ptr? */
    return 0;
}

この場合、変数xの有効期間は戻り値で終了しfoo()ます。ただし、 へのポインタはによってx格納されています。この場合、ローカル変数へのポインターを に渡すのはエラーでした。g_ptrbar()foo()xbar()

これが意味することは、ローカル変数へのポインターを関数に渡すことが有効かどうかを知るためには、その関数がそれに対して何をするかを知る必要があるということです。

于 2013-07-22T23:01:23.843 に答える
1

これらの変数はスタックに割り当てられます。それらを宣言した関数から戻らない限り、それらは有効なままです。

于 2013-07-22T22:57:54.893 に答える