コンマ式 には、1 つのコンマによって分離される任意の型の 2 つのオペランドが含まれ、左から右への結合順序があります。左方オペランドは完全に評価されますが、副次作用が生じる可能性があり、値があれば、この値は廃棄されます。その上で、右方オペランドが評価されます。 コンマ式の結果の型と値は、通常の単項型変換が行われた後のその右方オペランドの型と値になります。C の場合、コンマ式の結果は左辺値ではありません。C++ では、右方オペランドが左辺値の場合、結果は左辺値です。 次のステートメントは同じです。
r = (a,b,...,c); a; b; r = c;
相違点として、コンマ演算子は、ループ制御式などの式のコンテキストに適したものとすることができます。
同様に、複合式のアドレスは、右方オペランドが左辺値の場合に取得が可能です。
&(a, b) a, &b
コンマ演算子には結合順位があるため、コンマで分離された任意の数の式によって、単一式が形成されます。コンマ演算子を使用することによって、副次式が左から右に確実に評価され、最後の値が式全体の値になります。
次の例では 、omega が 11 の場合は、式は delta を増分し、 値 3 を alpha に代入します。
alpha = (delta++, omega % 4);
評価順序点は、第 1 オペランドの評価後に生じます。delta の値は廃棄されます。
例えば、次の式
intensity++, shade * increment, rotate(direction);
の値は、次の式の値になります。
rotate(direction)
コンマ演算子の基本的な使用目的は、次のような状況で、副次作用をもたらすことです。
コンマ文字が使用されるコンテキストでは、あいまいさを避けるために括弧が必要になります。例えば、次の関数
f(a, (t = 3, t + 2), c);
の引き数は、値 a、値 5、および値 c の 3 個だけです。括 弧を必要とするその他のコンテキストとしては、構造体および共用体宣言子内のフィールド長の式、 列挙宣言子リストの列挙値の式、ならびに宣言および初期化指定子の初期化式があります。
先の例では、コンマを使用して関数呼び出しにおける引き数の式を分離しています。このコンテキストでは、これにより関数引き数の評価順序 (左から右) が保証されるわけではありません。
次の表では、いくつかのコンマ演算子の
使用例を示します。
ステートメント | 効果 |
---|---|
for (i=0; i<2; ++i, f() ); | for ステートメント では、i が増分され 、反復のたびに f() が呼び出されます。 |
if ( f(), ++i, i>1 ) { /* ... */ } | if 文では、関数 f() が呼び出され、変数 i が増分され、 変数 i が値に対してテストされます。このコンマ式内の最初の 2 つの式は、式 i>1 の 前に評価されます。最初の 2 つの式の結果に関係なく 、3 番目の式が評価され、その結果が if 文を処理するかどうかを判別します。 |
func( ( ++a, f(a) ) ); | func() への関数呼び出しでは、 a が増分され、結果の値が関数 f() に渡され、 f() の戻り値が f() に渡されます。 関数 func() には、引き数が 1 つだけ渡されます。 これは、関数引き数のリスト内で、コンマ式が括弧で囲まれているからです。 |
関連参照