59

for他の人のコードを読んでいるときに、非常に奇妙なループを見たことがあります。C でループの完全な構文説明を検索しようとしましたforが、「for」という単語が関連のない文に表示され、Google で効果的に検索することがほとんど不可能になるため、非常に困難です。

このスレッドを読んだ後、この質問が頭に浮かび、再び興味をそそられました。

ここforに:

for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);

中間の条件では、2 つのコードを区切るコンマがありますが、このコンマは何をするのでしょうか? 右側のカンマは と の両方になるのでわかりa>>=1ますb<<=1

しかし、ループ終了条件内では何が起こるのでしょうか? p==0、いつ、または両方が発生したときに終了しますa==1か?

誰かがこれを理解するのを手伝ってくれて、完全なforループ構文の説明の方向性を教えてくれるとうれしいです.

4

6 に答える 6

130

コンマは for ループを除外するものではありません。それはコンマ演算子です。

x = (a, b);

最初に a を実行し、次に b を実行し、次に x を b の値に設定します。

for 構文は次のとおりです。

for (init; condition; increment)
    ...

これは(無視continuebreakて今のところ)以下と多少同等です:

init;
while (condition) {
    ...
    increment;
}

したがって、for ループの例は (再び and を無視しcontinuebreak) と同等です。

p=0;
while (p+=(a&1)*b,a!=1) {
    ...
    a>>=1,b<<=1;
}

あたかもそうであるかのように動作します(再び無視してcontinueand break):

p=0; 
while (true) {
    p+=(a&1)*b;
    if (a == 1) break;
    ...
    a>>=1;
    b<<=1;
}

上記の while ループへの単純化された変換には含まれていなかった for ループの 2 つの追加の詳細:

  • 条件が省略されている場合は、常に省略されます( 、、または他の何かがループを中断しtrueない限り、無限ループになります)。breakgoto
  • は、インクリメントをスキップする while ループ内のcontinueとは異なり、インクリメントの直前にラベルへの goto であるかのように動作します。continue

また、カンマ演算子に関する重要な詳細: これは&&andのようなシーケンス ポイント||です (これが、カンマ演算子を別々のステートメントに分割して、その意味をそのまま保持できる理由です)。


C99 の変更点

C99 標準には、この説明の前半で言及されていないいくつかのニュアンスが導入されています (これは C89/C90 に非常に適しています)。

まず、すべてのループはそれ自体がブロックです。効果的に、

for (...) { ... }

それ自体が一対の中かっこで包まれています

{
for (...) { ... }
}

標準は次のように述べています。

ISO/IEC 9899:1999 §6.8.5 反復ステートメント

¶5 反復ステートメントは、そのスコープがそれを囲むブロックのスコープの厳密なサブセットであるブロックです。ループ本体は、スコープが反復ステートメントのスコープの厳密なサブセットであるブロックでもあります。

これは、余分な中括弧のセットの観点から、根拠にも説明されています。

第二に、initC99 の部分は、次のように (単一の) 宣言にすることができます。

for (int i = 0; i < sizeof(something); i++) { ... }

これで、「ループにラップされたブロック」が本領を発揮します。iループ外で変数にアクセスできない理由を説明しています。複数の変数を宣言できますが、それらはすべて同じ型である必要があります。

for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }

標準は次のように述べています。

ISO/IEC 9899:1999 §6.8.5.3 for ステートメント

ステートメント

for ( clause-1 ; expression-2 ; expression-3 ) statement

式 expression-2 は、ループ本体の各実行前に評価される制御式です。式 expression-3 は、ループ本体の各実行後に void 式として評価されます。clause-1 が宣言である場合、それが宣言する変数の有効範囲は、残りの宣言とループ全体 (他の 2 つの式を含む) です。制御式の最初の評価の前の実行順序で到達します。句-1 が式である場合、制御式の最初の評価の前に void 式として評価されます。133)

句-1 と式-3 は両方とも省略できます。省略された式-2 は、ゼロ以外の定数に置き換えられます。

133)したがって、句-1 はループの初期化を指定し、おそらくループで使用する 1 つまたは複数の変数を宣言します。制御式である expression-2 は、式が 0 に等しくなるまでループの実行が続くように、各反復の前に行われる評価を指定します。また、expression-3 は、各反復の後に実行される操作 (インクリメントなど) を指定します。

于 2008-11-09T21:47:03.267 に答える
8

コンマは単に 2 つの式を区切るだけで、通常の式が許可されている C のどこでも有効です。これらは左から順に実行されます。一番右の式の値は、式全体の値です。

forループは 3 つの部分で構成され、そのいずれも空である場合があります。1 つ (1 つ目) は最初に実行され、もう 1 つ (3 つ目) は各反復の最後に実行されます。これらの部分は通常、それぞれカウンターを初期化し、インクリメントします。しかし、彼らは何でもするかもしれません。

2 番目の部分は、各実行の開始時に実行されるテストです。テストの結果が である場合false、ループは中止されます。それだけです。

于 2008-11-09T21:46:10.897 に答える
5

C スタイルの for ループは、次の 3 つの式で構成されます。

for (initializer; condition; counter) statement_or_statement_block;
  • イニシャライザは、ループの開始時に 1 回実行されます。
  • 条件は、各反復の前にチェックされます。ループは、評価が true である限り実行されます。
  • カウンターは、反復ごとに 1 回実行されます。

これらの各部分は、ループを記述する言語で有効な式にすることができます。つまり、より創造的に使用できるということです。前にやりたいことはすべてイニシャライザに入れることができ、その間にやりたいことはすべて、ループが本体を持たなくなるまで、条件またはカウンターに入れることができます。

これを実現するには、コンマ演算子が非常に便利です。式を連鎖させて、単一の新しい式を形成することができます。ほとんどの場合、for ループでそのように使用されますが、コンマ演算子のその他の意味 (値の代入に関する考慮事項など) は重要ではありません。

構文を創造的に使用することで賢いことを行うことができますが、そうする本当に正当な理由が見つかるまで、私はそれを避けます. for ループでコード ゴルフをプレイすると、コードの読み取りと理解 (および保守) が難しくなります。

ウィキペディアには for ループに関する素晴らしい記事もあります。

于 2008-11-09T21:57:58.580 に答える
2

forループではすべてがオプションです。複数の変数を初期化したり、複数の条件をチェックしたり、カンマ演算子を使用して複数の変数を反復したりできます。

次のforループは無限ループに入ります。状態を確認の上、ご注意ください。

for(;;) 
于 2009-03-09T14:04:22.537 に答える
0

Konrad は、私が繰り返したい重要なポイントを述べました。最も右側の式の値は、式全体の値です。

for ループの「条件」セクションに 2 つのテストを配置すると、Gnu コンパイラがこの警告を表示しました。

warning: left-hand operand of comma expression has no effect

私が実際に「条件」として意図したのは、「&&」で区切られた 2 つのテストです。コンラッドの声明によると、コンマの右側のテストのみが条件に影響します。

于 2010-04-13T18:11:15.937 に答える
-1

for ループは特定の時間の実行です for(;;)

for ループのシンテックス

為に(;;)

また

for (イニシャライザ; 条件; カウンタ)

例 (rmv=1;rmv<=15;rmv++)

forブロックで15回まで実行

1.値を開始するため、最初に値を初期化します

(例)rmv=1 または rmv=2

2. 2 番目のステートメントは、条件が true または false であるかどうかをテストし、条件が true である回数を実行し、for ループを実行し、条件が false である場合、ブロックを終了します。

例: i=5;i<=10 条件は真です

i=10;i<10 the condition is false terminate for block,

3.3番目はインクリメントまたはデクリメントです

(例)rmv++ または ++rmv

于 2014-10-14T11:15:07.350 に答える