web-dev-qa-db-ja.com

「for(;;)」は「while(TRUE)」より高速ですか?そうでない場合、なぜ人々はそれを使用しますか?

for (;;) {
    //Something to be done repeatedly
}

私はこの種のものが頻繁に使用されるのを見ましたが、それはむしろ奇妙だと思います... while(true)、またはそれらの線に沿った何かを言うのはもっと明確ではないでしょうか?

私は推測しています(多くのプログラマが暗号化コードに頼る理由であるように)これは小さなマージンです。

なぜ、そして本当にそれだけの価値があるのか​​?もしそうなら、なぜこのように定義しないのですか:

#define while(true) for(;;)

参照: どちらが速いか:while(1)またはwhile(2)?

158
Chris Cooper
  1. 速くありません。
  2. 本当に気になる場合は、ご使​​用のプラットフォーム用のアセンブラー出力でコンパイルし、確認してください。
  3. 関係ありません。これは重要ではありません。無限ループを好きなように書いてください。
255
Ben Zotto

私は2つの理由でfor(;;)を好みます。

1つは、一部のコンパイラがwhile(true)で警告を生成することです(「ループ条件が一定」など)。警告を避けることは常に良いことです。

もう1つは、for(;;)がより明確でわかりやすいと思うことです。無限ループが必要です。文字通りhas条件なし、何にも依存しません。私はそれを打ち破るために何かをするまで、それが永遠に続くことを望んでいます。

while(true)では、何と関係があるのでしょうか?私はtrueがfalseになるまでループすることに興味がありません。これはこの形式が文字通り言うことです(trueがtrueの間にループします)。ループしたいだけです。

いいえ、パフォーマンスの違いはまったくありません。

169
jalf

個人的にはfor (;;)を使用します。これには数字が含まれていないため、単なるキーワードです。 while (true)while (1)while (42)while (!0)などよりも好きです。

56
ta.speot.is

デニスリッチーのため

  • 私がfor (;;)を使い始めたのは、それがデニスリッチーがK&Rでそれを行う方法だからです。

  • これは慣用的なC/C++です。 C/C++空間で多くのことをするつもりなら、長い目で見れば慣れる方が良いでしょう。

  • きみの #defineは動作しません。#defineされているものはCの識別子のように見えなければならないからです。

  • 最新のコンパイラーはすべて、2つの構成体に対して同じコードを生成します。

49
Mark Harrison

正しいコンパイラーでは確かに高速ではありません。これらは両方とも無条件ジャンプにコンパイルされます。 forバージョンは(Neilが言ったように)入力しやすく、forループ構文を理解すれば明確になります。

好奇心が強い方は、gcc 4.4.1がx86に私に与えてくれるものを以下に示します。両方ともx86 [〜#〜] jmp [〜#〜] 命令を使用します。

void while_infinite()
{
    while(1)
    {
    puts("while");
    }
}

void for_infinite()
{
    for(;;)
    {
    puts("for");
    }
}

コンパイル(一部):

.LC0:
.string "while"
.text
.globl while_infinite
    .type   while_infinite, @function
while_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L2:
    movl    $.LC0, (%esp)
    call    puts
    jmp .L2
    .size   while_infinite, .-while_infinite
    .section    .rodata
.LC1:
    .string "for"
    .text
.globl for_infinite
    .type   for_infinite, @function
for_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L5:
    movl    $.LC1, (%esp)
    call    puts
    jmp .L5
    .size   for_infinite, .-for_infinite
46

私はfor (;;)が好きです。なぜなら、それは異なるCライクな言語で最も一貫しているからです。

C++ではwhile (true)は問題ありませんが、Cではtrueを定義するためにヘッダーに依存しますが、TRUEも一般的に使用されるマクロです。 while (1)を使用する場合、CおよびC++、およびJavaScriptでは正しいが、JavaまたはC#ではなく、ループ条件がwhile (true)またはwhile (1 == 1)。PHPでは、キーワードは大文字と小文字を区別しませんが、言語は大文字のTRUEを優先します。

ただし、for (;;)はこれらすべての言語で常に完全に正しいです。

41
Boann

個人的にはfor (;;)イディオム(while (TRUE)と同じコードにコンパイルされます)を好みます。

while (TRUE)を使用すると、ある意味で読みやすくなる可能性があるため、それが際立つため、for (;;)イディオムを使用することにしました

無限ループ構造は、コードで簡単に認識または呼び出されるはずです。個人的には、for (;;)スタイルはwhile (TRUE)while (1)よりも優れていると思います。

また、whileループの制御式が定数である場合、一部のコンパイラが警告を発行することを思い出します。私はそれがあまりにも多く起こるとは思いませんが、偽の警告の可能性があるだけでそれを避けたいと思っています。

21
Michael Burr

次のような#defineがあるため、一部の人々がそれを好むのを見てきました。

#define EVER ;;

これにより、彼らはこれを書くことができます:

for (EVER)
{
    /* blah */
}
17
rmeador

どうでしょう(あなたの言語がそれをサポートしている場合):

start:
/* BLAH */
goto start;
16
bungle

生成されるマシンコードに関して違いはありません。

しかし、トレンドに逆らうために、while(TRUE)フォームはfor(;;)よりもはるかに読みやすく直感的であり、コーディングガイドラインの読みやすさと明快さは、あらゆる理由よりもはるかに重要な理由だと主張しますfor(;;)アプローチについて聞いた(私はコーディングガイドラインの根拠を、確固たる推論および/または有効性の証明に自分でしたい)。

12
Jason Williams

よく知られたパターンだけでなく、C(およびC++)の標準的なイディオム

11
James McLeod

コードがコンパイラによって最適化されている場合、両方は同じである必要があります。最適化の意味を説明するために、MSVC 10で作成されたサンプルコードを次に示します。

int x = 0;

while(true) // for(;;)
{
    x +=1;

    printf("%d", x);
}

デバッグモード(最適化(/ Od)なし)でビルドした場合、逆アセンブリは明確な違いを示します。 true内のwhile条件に関する追加の指示があります。

while(true)
00D313A5  mov         eax,1                //extra 
00D313AA  test        eax,eax              //extra
00D313AC  je          main+39h (0D313B9h)  //extra
    {
        x +=1;
00D313AE  mov         eax,dword ptr [x]  
00D313B1  add         eax,1  
00D313B4  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D313B7  jmp         main+25h (0D313A5h)  


for(;;)
    {
        x +=1;
00D213A5  mov         eax,dword ptr [x]  
00D213A8  add         eax,1  
00D213AB  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D213AE  jmp         main+25h (0D213A5h)  

ただし、リリースモードでコードをビルドすると(デフォルトでは速度(/ O2)を最大化)、両方で同じ出力が得られます。両方のループが1つのジャンプ命令に削減されます。

for(;;)
    {
        x +=1;
01291010  inc         esi  

        printf("%d", x);
    ...
    }
0129101C  jmp         main+10h (1291010h)  

    while(true)
    {
        x +=1;
00311010  inc         esi  

        printf("%d", x);
    ...
    }
0031101C  jmp         main+10h (311010h)  

速度の最適化が有効になっている適切なコンパイラーでは、どちらを使用してもかまいません。

11
SylvanBlack
while(true)

visual Studioで警告を生成します(条件は一定です)。私が働いたほとんどの場所は、エラーとして警告を伴う実動ビルドをコンパイルします。そう

for(;;)

推奨されます。

11
Michael

どちらの方が速いかは個人の好みの問題です。個人的に、私はタッチタイピストであり、プログラミング中にキーボードを見ることはありません-キーボードの104個のキーすべてをタッチタイプできます。

「while(TRUE)」と入力する方が速い場合があります。

指の動きの測定値を精神的に追加し、合計しました。 「for(;;)」には前後に約12キー幅の移動があります(ホームキーとキーの間、およびホームキーとSHIFTキーの間)「while(TRUE)」には前後に約14キー幅の移動があります。第4。

ただし、後者を入力するときのエラーは非常に少なくなります。私は精神的に一度に言葉で考えるので、「nIdx」などの頭字語よりも「nIndex」のようなものを入力する方が速いと思います。 -単語を入力します(自転車に乗るなど)

(私のTypingTest.comベンチマーク= 136 WPM)

9
Mark Rejhon

すべての良い答え-動作はまったく同じでなければなりません。

ただし、DID=違いを生むと仮定します。そのうちの1つが反復ごとにさらに3つの命令を必要とすると仮定します。

気にする必要がありますか?

ループ内で行うことがほとんど何もしないである場合にのみ、これはほとんど決してないの場合です。

私のポイントは、マイクロ最適化とマクロ最適化があります。マイクロ最適化は、「減量のために散髪をする」ようなものです。

6
Mike Dunlavey

価値のあるコンパイラが異なるコードを生成するとは想像できません。たとえそれが行われたとしても、特定のコンパイラーをテストせずに決定する方法はなく、より効率的でした。

ただし、次の理由から、for(;;)をお勧めします。

  • 私が使用したいくつかのコンパイラは、適切な警告レベル設定でwhile(true)の定数式警告を生成します。

  • あなたの例では、マクロTRUEは期待どおりに定義されていない可能性があります

  • while(1)while(true)while(1==1)など、無限whileループにはさまざまなバリエーションがあります。そのため、for(;;)は一貫性を高める可能性があります。

5
Clifford
_for(;;Sleep(50))
{
    // Lots of code
}
_

以下よりも明確です:

_while(true)
{
    // Lots of code
    Sleep(50);
}
_

Sleep()を使用していない場合、これは当てはまりません。

5
Armada

「永久」ループは、組み込みシステムでバックグラウンドループとして一般的です。一部の人々はそれを次のように実装します:

for (; ;)
{
 // Stuff done in background loop
}

そして時々それは次のように実装されます:

while (TRUE /* or use 1 */)
{
 // Stuff done in background loop
}

さらに別の実装は次のとおりです。

do
{
 // Stuff done in background loop
} while (1 /* or TRUE */);

最適化コンパイラは、これらのフラグメントに対して同じまたは類似のアセンブリコードを生成する必要があります。 1つの重要な注意:ループの実行時間は、これらのループが永遠に続き、処理セクションにより多くの時間が費やされるため、大きな関心事ではありません。

4
Thomas Matthews

While(true)はfor(;;)より読みやすいと思います-プログラマーがforループで何かを見逃しているように見えます :)

誰がより速いかを気にする人

2
nik

「for(;;)」を使用する最も重要な理由は、探索的プログラミングを行うときに「while(TRUE)」を使用することへの恐怖です。 「for」で繰り返しの量を制御するのが簡単で、「for」ループを無限に変換するのも簡単です。

たとえば、再帰関数を作成する場合、無限ループに変換する前に関数の呼び出し量を制限できます。

    for(int i=0;i<1000;i++) recursiveFunction(oneParam);

私の機能が確信できたら、それを無限ループに変換します:

    for(;;) recursiveFunction(oneParam);
2