3

次のようなtest.cファイルがある場合

#include ...
int global = 0;

 int main() {
 int local1 = 0;

  while(1) {
  int local2 = 0;
  // Do some operation with one of them
 }
 return 0;
}

では、while ループでこの変数の 1 つを使用する必要がある場合、どの変数が優先されるでしょうか?

ここでは少し漠然としているかもしれませんが、時間/空間の割り当ての違いが実際に関連しているかどうかを知りたい.

4

5 に答える 5

5

forループ内で変数を宣言すると、反復ごとに変数が作成/破棄されるかどうか疑問に思っている場合は、特に心配する必要はありません。これらの変数は実行時に動的に割り当てられるわけではなく、mallocここでは何も行われていません。ループ内で使用するためにメモリが確保されているだけです。したがって、変数をループの外側に配置することは、パフォーマンスの点でループの外側に配置することとまったく同じです。

ここでの本当の違いは、パフォーマンスではなくスコープです。グローバル変数とローカル変数のどちらを使用するかは、この変数を表示する場所にのみ影響します。

于 2011-06-08T19:44:56.530 に答える
2

Cコンパイラは、関数に対してローカルで宣言された変数を最適化するのに時間がかかります。グローバル変数には、「プロシージャ間データフロー分析」を実行するためのオプティマイザが必要ですが、これは一般的には実行されません。

違いの例として、すべての宣言が変数をゼロに初期化すると考えてください。ただし、グローバル変数の場合、コンパイラは、サンプル関数で使用する前に、プログラム内の制御フローがグローバルを変更できないことを確認しない限り、その情報を使用できません。ローカルで宣言された(「自動」)変数の場合、初期値を別の関数で変更する方法はありません(特に、コンパイラーはそれらのアドレスがサブ関数に渡されないことを確認します)。 「強制終了定義」および「値の活性」分析を実行して、一部のコードパスでゼロ値を想定できるかどうかを判断します。

2つのローカル変数のうち、ガイドラインとして、オプティマイザーは、より小さな(より制限された)スコープで変数へのアクセスを最適化するためのより簡単な時間を常に持っています。

上記のように、オプティマイザー-メタ最適化よりもセマンティクスへのバイアスに関する他の回答が正しいことをお勧めします。コードを最もよく読み取る変数を使用すると、def-use最適化の計算を支援するよりも多くの時間が返されます。

一般に、グローバル変数、または絶対に必要なものよりも広くアクセスできる変数の使用は避けてください。変数のスコープを制限すると、後のプログラム保守中にバグが発生するのを防ぐのに役立ちます。

于 2011-06-08T19:46:59.323 に答える
2

このような決定は、パフォーマンスではなくセマンティクスに基づくべきです。グローバル変数のセマンティックな動作が必要でない限り、常に自動 (ローカルの非静的) 変数を使用する必要があります。

他の人が言ったように、そして確かに言うように、パフォーマンスに違いはほとんどありません. ある場合、自動変数はより高速になります。

于 2011-06-08T19:43:44.200 に答える
2

変数には、静的 (グローバル)、スタック (自動)、およびレジスタの 3 つの大まかなクラスがあります。

レジスタ変数は、CPU レジスタに格納されます。レジスタは、CPU パイプラインに統合された非常に高速なワード サイズのメモリです。それらは無料でアクセスできますが、非常に限られた数しかありません (通常、プロセッサと実行している操作に応じて 8 から 32 の間です)。

スタック変数は、スタックと呼ばれる RAM の領域に格納されます。スタックはほとんど常にキャッシュにあるため、スタック変数は通常、アクセスに 1 ~ 4 サイクルかかります。

一般に、ローカル変数は、レジスターまたはスタックのいずれかに置くことができます。それらが関数の先頭に割り当てられているか、ループ内に割り当てられているかは問題ではありません。関数呼び出しごとに 1 回だけ割り当てられ、割り当ては基本的に自由です。コンパイラーは可能な限り変数をレジスターに入れますが、アクティブな変数がレジスターよりも多い場合、それらはすべて収まりません。また、変数のアドレスを取得する場合、レジスタにはアドレスがないため、スタックに格納する必要があります。

グローバル変数と静的変数は別物です。通常は頻繁にアクセスされるわけではないため、キャッシュに存在しない可能性があり、アクセスに数百サイクルかかる場合があります。また、コンパイラは事前にグローバル変数のアドレスを認識していない可能性があるため、ルックアップが必要になる場合がありますが、これもコストがかかります。

他の方もおっしゃっている通り、あまり気にしないでください。知っておくと良いことは間違いありませんが、プログラムの作成方法に影響を与えるべきではありません。意味のあるコードを記述し、コンパイラーに最適化について心配させます。コンパイラの開発に取り掛かると、それについて心配し始めることができます。:)


編集:割り当ての詳細:

レジスタ変数はコンパイラによって割り当てられるため、ランタイム コストは発生しません。コードは、値が生成されるとすぐにレジスタに値を入れます。

スタック変数は、実行時にプログラムによって割り当てられます。通常、関数が呼び出されると、最初にすべてのローカル変数用に十分なスタック スペースが確保されます。したがって、変数ごとのコストはありません。

于 2011-06-08T20:05:18.077 に答える
2

パフォーマンスの違いについて疑問がある場合: ほとんどの場合、違いはありません。理論上のパフォーマンスの違いがある場合、それらを測定するテストを実際に考案するのは難しいでしょう。

于 2011-06-08T19:41:23.400 に答える