2

C には何もしないステートメントがたくさんあります。つまり、それらを削除しても、プログラムの動作に目に見える変化はありません。

C 標準によると、C コンパイラはこれらの冗長なステートメントを最適化できますか?

たとえば、次のようなコードがあるとします。

#include <stdio.h>

void f(void);

int main(void){

    printf("a");
    f(); // function call statement that provably does nothing

    printf("b");
    1000; // redundant expression statement

    printf("c");
    ; // null statement

    printf("d");
    int x = 1; // assignment statement that is not used

    printf("e");

    return 0;
}

void f(void){
    1000; // redundant expression statement
    ; // null statement
    int x = 1; // assignment statement that is not used
}

コンパイラは、以下と同じオブジェクト コードを生成できますか? :

#include <stdio.h>

void f(void);

int main(void){
    printf("a");
    printf("b");
    printf("c");
    printf("d");
    printf("e");
    return 0;
}

void f(void){
}
4

4 に答える 4

7

80 年代に、私の友人が、円周率を計算するアルゴリズムを実行し、それを単に出力するプログラムを書いたと私に言いました。

コンパイルされた exe ファイルを見たとき、彼はコンパイラが基本的に出力 3.14159 を生成したことに驚きました。

つまり、C (またはその他の言語) コンパイラは、プログラムの動作を変更しないあらゆることを実行できます。

これは Java などにも当てはまり、JVM は速度を向上させるためにいくつかの手法を採用しています (たとえば、ループの「アンラップ」により、ループのオーバーヘッドを経ずにコードが順次実行されるなど)。

于 2013-10-22T06:21:03.210 に答える
6

C標準は次のように述べています(C11 5.1.2.3/4):

抽象マシンでは、すべての式がセマンティクスで指定されたとおりに評価されます。実際の実装では、式の値が使用されておらず、必要な副作用 (関数の呼び出しや揮発性オブジェクトへのアクセスによるものを含む) が生成されていないと推測できる場合、式の一部を評価する必要はありません。

したがって、関数に「必要な」副作用が含まれていない限り、コンパイラは関数呼び出しを自由に最適化できます。言葉遣いは少し曖昧で、さまざまな方法で解釈される可能性があります。しかし、実際には、すべてのコンパイラが空の関数を最適化する可能性が高くなります。

于 2013-10-22T06:22:31.210 に答える
0

コンパイラが何を削除するか、およびそれがどの程度の長さになるかは、コンパイラに大きく依存します。一部のコンパイラは、一部の設定で静的関数全体 (呼び出しだけでなく定義も) を削除することさえありますが、他のコンパイラは非常に保守的で何も削除しない場合があります。言い換えれば、それは記述されているほとんどのオブジェクト コードである可能性があります。

int main(int argc, char**argv) {
   printf("abcde")
   return 0;
}
于 2013-10-22T06:19:36.677 に答える