2012-01-27 1 views
2

、与えられたこれらの4例:これらのタイプの変数の初期化とのパフォーマンスの違いはありますか? (関数のような)ローカルスコープ内

(1)

int x; 
int y; 
// code... 
x = 4; 
y = 5; 

(2)

int x = 4; 
int y = 5; 
// code... 

(3)

// code... 
int x = 4; 
// code... 
int y = 5; 

(4)

// any other possibility 

私の変数を宣言して開始するフォームにはパフォーマンスの違いがありますか、それとも私のためにコンパイルしてくださいか?

編集

私はその優れた性能のために良いだろう、ほとんどの最初の行ですべての宣言を配置することをしばしば読んだので、私は聞いていますのよ。のような:

func(){ 
    int x,y,z,w; 
    long bla,ble; 
    MYTYPE weeee; 
    // more declarations.. 
    //code.. 
} 

しかし、私は理由を知りませんでした。

+0

Cで#3を実行できますが、C++でしか実行できません。 – dasblinkenlight

+0

パフォーマンスに差がある場合は、測定するのが簡単ではない可能性があります。つまり、最もよく見える方法や読みやすい方法を使用できます。 –

+5

@dasblinkenlight C99の時点で、あなたは本当にできます。 – unwind

答えて

1

、ボンネットの下に何が起こっているか確認するためにアセンブラを見ている私は、その優れたが、そのほとんどの最初の行ですべての宣言を配置することをしばしば読んだので、私は聞いていますのよパフォーマンスにとってはより良いでしょう。

私はこれが純粋なナンセンスであることを保証することができます。このようなステートメントを作成している人は、Cコードが機械コードにどのように変換されるかは全く分かりません。

3つの例のいずれかが異なるマシンコードを与えた場合、私は非常に驚くでしょう。


しかし特殊なケースが存在する:変数が「グローバル」またはstaticとして宣言されていた、そして、彼らは、静的記憶域期間を持つことになります。 main()が呼び出される前に初期化されます。プログラマによって明示的に初期化されていないすべてのグローバル/統計はゼロに設定されます。だから、その場合には、あなたの例1)は遅くされているでしょう:の99.9%でそう

int x; /* global variable, no explicit init so it will get set to 
      zero before main() is called */ 
... 
x = 4; // variable gets set a second time, elsewhere, in "runtime" 

は、これら二つの間の性能差はしかし、そうちょうど1つのCPU命令である

int x = 4; // global variable, gets initialized before main() is called 

より遅いですすべてのアプリケーションは関係ありません。

0

予測可能なパフォーマンスの違いはありません。

1

// codeブロックのどれもがxyに触れていない場合、これらのオプションでパフォーマンスの違いが認識される可能性はほとんどありません。

コンパイラを使用してハードウェアアーキテクチャに何が起こっているかを知りたい場合は、コードをベンチマークしたり、生成されたアセンブリを調べたりできます。

+0

+1アセンブリの出力を見てください。私は、ほとんどのプロファイラーがこのレベルの細かさで苦労していると思うので、ベンチマークのためには本当に大きなループについて話しています。 –

0

コンパイラが本当にダムの場合、2番目の形式が最適です。そうでなければ、他のフォームを最適化します。

+0

なぜですか?それは意味をなさない。 2番目の例がより高速のマシンコードをもたらした歴史の中で、任意のダムコンパイラの例を挙げることができますか? – Lundin

+0

歴史的なコンパイラについてはわかりませんが、最初のコードは 'sub rsp、8' ...' mov [rsp + 4]、4'' mov [rsp]、5' 2番目のものは 'push 0x00040005'のようなものになります – asaelr

+0

私はそれを疑います。いずれのケースでも、4,5値がCPUレジスタまたはスタックに直接格納されることになります。 – Lundin

3

Cは公演について何も言わない。

(C99,5.1.2.3p1) "この国際標準の意味論的記述は、最適化問題が無関係な抽象機械の動作を記述している。

これは実装に依存しますが、良いコンパイラであれば同じコードが生成される可能性があります。

0

Cでは、違いはないと思います。 C++では、コンストラクタが呼び出されているかどうかと、一時オブジェクトがループ内で宣言されているかどうかに基づいて、呼び出された回数に基づいて大きな違いがあります。

C99では、関数が入力されたとき、またはブロックが入力されたときに、遅延宣言がスタック領域を割り当てるかどうかはわかりません。これは、オプティマイザが処理する必要のある軽微なパフォーマンス上の影響に似ています。エクスの答えあたり、良好なアプローチは

1

1)デバッグにがあります。です。コンパイラはリリース時にあなたの世話をする必要があります。

2)これは可読性のために好きかもしれません。コンパイラは一定の値を完全に消去することができました。

3)これは違いがあります。ローカル宣言はしばしば最適ですが、それは実際のコンストラクタがいくつかの作業を行うC++ではより重要です。時には、大きなオブジェクトがループから抜かれた場合に違いを測定することもあります(しかし、コンパイラがそれを行う必要があります)。

私は多くの場合、すべての宣言をパフォーマンスのために最も最初の行に置く方が良いという理由から、私は尋ねています。

そうではありません。私はその考えが昨年の言語制限から来ていると思います。とにかく、「可能な限り地元で」は定期的に最善です。もちろん、これはコンパイラ、ハードウェア、実装などによって異なる場合があります。

Cでは、スタックの割り当てと初期化は簡単ではないため、コンパイラはこれを十分に処理して、ほとんどの場合パフォーマンスに問題はありません。

現実世界のベンチマークとプロファイリングを試してみてください。 asmを見て(Aixが述べたように)助けることもできます。

あなたがfarアセンブリを書くのではなく、毎日のプロファイリングを行わない場合、これは厳密にCであり、書く方法を変更する価値はありません。

1

多くの場合、すべての宣言を最初の行に置きパフォーマンスを向上させる方がよいと私は尋ねています。同様に:

func(){ 
    int x,y,z,w; 
    long bla,ble; 
    MYTYPE weeee; 
    // more declarations.. 
    //code.. 
} 

いいえ、これを行うための唯一の理由は、初期のCであなたは、関数のコードの前にすべての宣言を入れてを持っていたということです。

このルールは前世紀の終わりに変更されました。

関連する問題