0

以下を考えると:

len = strlen(str);
/* code that does not read from len */
len = new_len;

コンパイラに依存して最初の行を削除できますか?

コード生成スクリプトを書いています。最初の行は 1 つの場所で生成されますが、それに続くすべての行は別の場所で (子孫クラスの仮想関数によって) 生成されます。ほとんどの場合、len は必要ありません。時々ですが、そうです。すべての場合に設定して、必要でない場合はコンパイラに行を削除させることができるのではないかと思います。

4

4 に答える 4

4

いいえ、もちろん、コンパイラによる最適化の選択に「依存」することはできません。

これらは、ユーザーの気まぐれ (コンパイラ コマンド ライン オプション) で、または異なるコンパイラ バージョンで変更できます。

あなたが記述している動作は言語標準では要求されていないため、コンパイラに依存して実装することはできません。

一方、確実にテストして、コンパイラーに可能な限り多くの最適化を行うように (再度) 要求することにより、最適化を「なだめる」ことを試みることができます。

于 2013-01-23T14:10:25.653 に答える
2

コンパイラはかなり賢いです。しかし、コンパイラが「未使用」の関数呼び出しを削除することに頼るのは、おそらく良い考えではありません。1 つには、コンパイラは、呼び出している関数を理解する必要があります (したがって、ほとんどのコンパイラは strlen が何を行い、それが他のものにどのように影響するかを理解しているため、ここでは strlen が良い例です) - 関数がコンパイラが「理解できるものではない場合」 "、それを最適化することはできません。

あなたがした場合:

 x = printf("Hello, World!\n");

 x = printf("World, Hello!\n");

コンパイラが最初の printf を削除して正しいことをしたと思いますか? おそらくそうではありません...したがって、コンパイラーが「副作用がない」と判断できない関数では、結果が使用されていなくても、コンパイラーは関数を呼び出す必要があります。副作用がないということは、通常の状況での手段です-たとえば、無効なポインターで strlen() を呼び出すことの副作用があります-コードはおそらくクラッシュします-しかし、それは「通常の状況」ではありません- strlen( を使用するのはかなり馬鹿げています)ポインタが有効かどうかを確認するだけですよね?

したがって、言い換えると、strlen を呼び出す前に、strlen() への呼び出しが本当に必要であることを確認するか、コンパイラが不要な strlen 呼び出しを生成する可能性があるという事実を受け入れる必要があります。

于 2013-01-23T14:24:14.713 に答える
1

最新のコンパイラは、冗長な割り当てを排除する優れた仕事をしているようです。VS 2008 と gcc 4.6 で次のスニペットを実行したところ、実際には strlen への呼び出し (むしろインライン化されたコード) が削除されました。どちらのコンパイラも、something()との両方something_else()が副作用を引き起こさないことを確認できました。これらへの呼び出しも削除されます。

これは、VC の /O1 と gcc の /O1 で発生します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int something(int len)  {
    if(len != len) {
        printf("%d\n", len);
    }
    return 0;
}

int something_else(int len) {
    return len * len;
}

int main(void) {
    char *s = malloc(1000);
    size_t len;
    strcpy(s, "Hello world");
    len = strlen(s);
    something(len);
    printf("%s\n", s);
    len += 8;
    something_else(len);
    len = 5;
    printf("%d\n", len);
    return 0;
}
于 2013-01-23T17:54:49.523 に答える
0

コンパイラと指定した最適化レベルによって異なります。

ここでは、関数呼び出しから最初に割り当てられます。その関数に副作用がある場合はどうなりますか?
したがって、コンパイラが最適化すると仮定することはできません。

最初の割り当てステートメントに副作用がなく、最適化レベルを十分に指定した場合 (gcc の場合は -O3 など)、最適化される可能性があります。

于 2013-01-23T14:11:04.007 に答える