3

私は、必要なときに些細な変数を定義する習慣を身につけようとしてきました。私はこのようなコードを書くことに注意してきました:

while (n < 10000) {
   int x = foo();
   [...]
}

xループ内にのみ存在する標準が完全に明確であることは知っていますが、これは技術的には、反復ごとに整数がスタックに割り当てられ、割り当てが解除されることを意味しますか?最適化コンパイラがこれを行う可能性は低いと思いますが、それは保証されていますか?

たとえば、次のように書く方がよいでしょうか。

int x;
while (n < 10000) {
   x = foo();
   [...]
}

私はこのコードを具体的に意味するのではなく、このようなあらゆる種類のループを意味します。

このように異なる単純なループについてgcc4.7.2で簡単なテストを行い、同じアセンブリが生成されましたが、私の質問は、標準によれば、これら2つは本当に同一ですか?

4

4 に答える 4

6

このような自動変数の「割り当て」はほとんど無料であることに注意してください。ほとんどのマシンでは、単一命令のスタックポインター調整であるか、コンパイラーがレジスターを使用します。この場合、何もする必要はありません。

また、変数はループが終了するまでスコープ内にとどまるため、ループが終了するまで変数を「削除」(=スタックポインターを再調整)する理由はまったくありません。コードのオーバーヘッドの反復が発生することは確かにありません。このような。

また、もちろん、コンパイラーは、必要に応じて、割り当てをループから完全に「移動」することができます。これにより、コードは、int x;前の2番目の例と同等になりますwhile。重要なことは、最初のバージョンは読みやすく、より厳密にローカライズされている、つまり人間にとってより良いということです。

于 2013-03-14T13:11:48.893 に答える
1

はい、xループ内の変数は技術的に各反復で定義され、各反復での呼び出しを介して初期化さfoo()れます。毎回異なる答えが出る場合foo()、これは問題ありません。毎回同じ答えが得られる場合は、最適化の機会です。初期化をループの外に移動します。このような単純な変数の場合、コンパイラは通常、スタックにバイトを予約します(レジスタにsizeof(int)保持できない場合)。これは、スコープ内にあるときに使用し、同じ関数の他の場所で他の変数にそのスペースを再利用できます。変数がVLA(可変長配列)の場合、割り当てはより複雑になります。xxx

分離された2つのフラグメントは同等ですが、違いはのスコープですx。ループの外側で宣言された例でxは、値はループが終了した後も持続します。ループ内でx宣言されているため、ループが終了するとアクセスできなくなります。あなたが書いた場合:

{
    int x;
    while (n < 10000)
    {
        x = foo();
        ...other stuff...
    }
}

その場合、2つのフラグメントは十分に同等になります。アセンブラレベルでは、どちらの場合も違いを見つけるのは難しいでしょう。

于 2013-03-14T13:16:47.403 に答える
1

私の個人的な見解は、そのようなマイクロ最適化について心配し始めると、失敗する運命にあるということです。ゲインは次のとおりです。

a)非常に小さい可能性が高い

b)ポータブルではない

私はあなたの意図を明確にするコード(つまり、ループ内でxを宣言する)に固執し、コンパイラーに効率を気にさせます。

于 2013-03-14T13:25:56.137 に答える
0

C標準には、どちらの場合でもコンパイラがコードを生成する方法を示すものはありません。必要に応じて、ループの反復ごとにスタックポインタを調整できます。

そうは言っても、次のようなVLAで何かおかしなことを始めない限り、次のようになります。

void bar(char *, char *);
void
foo(int x)
{
        int i;
        for (i = 0; i < x; i++) {
                char a[i], b[x - i];
                bar(a, b);
        }
}

コンパイラは、ほとんどの場合、関数の先頭に1つの大きなスタックフレームを割り当てるだけです。関数の最初に必要なものをすべて割り当てるのではなく、ブロック内の変数を作成および破棄するためのコードを生成するのは困難です。

于 2013-03-14T13:31:43.183 に答える