コンマは for ループを除外するものではありません。それはコンマ演算子です。
x = (a, b);
最初に a を実行し、次に b を実行し、次に x を b の値に設定します。
for 構文は次のとおりです。
for (init; condition; increment)
...
これは(無視continue
しbreak
て今のところ)以下と多少同等です:
init;
while (condition) {
...
increment;
}
したがって、for ループの例は (再び and を無視しcontinue
てbreak
) と同等です。
p=0;
while (p+=(a&1)*b,a!=1) {
...
a>>=1,b<<=1;
}
あたかもそうであるかのように動作します(再び無視してcontinue
and break
):
p=0;
while (true) {
p+=(a&1)*b;
if (a == 1) break;
...
a>>=1;
b<<=1;
}
上記の while ループへの単純化された変換には含まれていなかった for ループの 2 つの追加の詳細:
- 条件が省略されている場合は、常に省略されます( 、、または他の何かがループを中断し
true
ない限り、無限ループになります)。break
goto
- は、インクリメントをスキップする while ループ内の
continue
とは異なり、インクリメントの直前にラベルへの goto であるかのように動作します。continue
また、カンマ演算子に関する重要な詳細: これは&&
andのようなシーケンス ポイント||
です (これが、カンマ演算子を別々のステートメントに分割して、その意味をそのまま保持できる理由です)。
C99 の変更点
C99 標準には、この説明の前半で言及されていないいくつかのニュアンスが導入されています (これは C89/C90 に非常に適しています)。
まず、すべてのループはそれ自体がブロックです。効果的に、
for (...) { ... }
それ自体が一対の中かっこで包まれています
{
for (...) { ... }
}
標準は次のように述べています。
ISO/IEC 9899:1999 §6.8.5 反復ステートメント
¶5 反復ステートメントは、そのスコープがそれを囲むブロックのスコープの厳密なサブセットであるブロックです。ループ本体は、スコープが反復ステートメントのスコープの厳密なサブセットであるブロックでもあります。
これは、余分な中括弧のセットの観点から、根拠にも説明されています。
第二に、init
C99 の部分は、次のように (単一の) 宣言にすることができます。
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 は、各反復の後に実行される操作 (インクリメントなど) を指定します。