0

次のように、ループ内で配列のアイテムを使用するとします。

INS *in;
for (int i = 0; i < LEN; i++) {
    in = g_ins[i];
    if (strcmp(in->mne, str) == 0)
        return in;
}

インデックスを使用して各参照を参照すると、これはコンパイラによって上記のようなものに最適化されますか、それとも実際に各インデックスに何度もアクセスしますか?

for (int i = 0; i < LEN; i++) {
    if (strcmp(g_ins[i]->mne, str) == 0)
        return g_ins[i];
}
4

4 に答える 4

1

疑問がある場合は、試すことができます。たとえば、2 つのコードを関数に入れます。

INS * f1 (INS *g_ins, const char * str)
{
    for (int i = 0; i < LEN; i++) {
        INS *in = &g_ins[i];
        if (strcmp(in->mne, str) == 0)
            return in;
    }
    return NULL;
}

INS * f2 (INS *g_ins, const char * str)
{
    for (int i = 0; i < LEN; i++) {
        if (strcmp(g_ins[i].mne, str) == 0)
            return &g_ins[i];
    }
    return NULL;
}

-O2 と -S を付けてコンパイルします (例: gcc -std=c99 -O2 -S -Wall code.c -o code.s)。-O2 は最適化レベルを設定し、-S はアセンブラー コードを生成して停止するようにコンパイラーに指示します。

次に、アセンブラ コードを見てください。

アセンブラをよく理解していなくても、2 つの関数の相対的なサイズを理解できるはずです。関数の場合、それらは同じコードにコンパイルされます。

于 2012-08-15T14:30:07.220 に答える
1

コンパイラとコンパイラの設定に大きく依存します。

といっても、普段は気にすることはありません。

于 2012-08-15T13:52:18.973 に答える
0

ほぼすべてのレベルの最適化で、コンパイラはおそらく2つのフラグメントに対して同じコードを生成します。g_ins[i]実際、最適化を行わないと、の値を明示的に格納する必要がないため、明示的なローカル変数を含まないバージョンの方がうまくいく可能性があります。レジスターに入れて、それを2回使用するだけかもしれません。

ただし、使用しているコンパイラと最適化設定によって異なります。そして、ここでの違いが速いプログラムと遅いプログラムの違いになる可能性は低いです。

于 2012-08-15T14:09:45.787 に答える
0

ほとんどの場合、コンパイラは通常の設定ではそのようなことを回避します。変数はループの外側で宣言され、ループの後にINS * inがさらに使用されるかどうかは不明です。したがって、この段階をスキップしても、いくつかの保存を除いて、多くの最適化は行われません。命令ですが、後の段階で出力が破損する可能性があります。

于 2012-08-15T14:10:54.670 に答える