プログラミング言語のC/C++およびJavaScriptなどにおけるコンマ演算子(コンマえんざんし、)は、左オペランド(被演算子)を評価しその値を捨て、その後右オペランドを評価する演算子である。コンマの記号文字「,」が使用される。順次演算子(じゅんじえんざんし)もしくは順次評価演算子 (sequential-evaluation operator) と呼称されることもあるSequential-Evaluation Operator | Microsoft Learn順次評価演算子。日本産業規格(旧称:日本工業規格)のJIS X 3010:2003『プログラム言語C』およびJIS X 3014:2003『プログラム言語C++』では「コンマ演算子」と表記されている。「カンマ演算子」と表記されているドキュメントもあるカンマ演算子 - RAD Studioカンマ演算子 (,) - JavaScript | MDN。
コンマ演算子の値と型は右オペランドの値と型となる。Cでは右辺値だが、C++では右オペランドが左辺値であれば左辺値となる。また、左オペランドの評価に対する副作用(C++では一時変数の破棄を除く)が完了した後に右オペランドが評価されることが規格上保証されている。コンマ演算子の優先順位は最も低く規定されているC Operator Precedence - cppreference.comC++ Operator Precedence - cppreference.com。代入演算子=よりも低いため、例えばコンマ演算子の評価結果(右オペランド)を何らかの変数に代入したい場合は、括弧で囲んでx = (a, b);のように書く必要がある。
複数の変数の宣言、配列や構造体の初期化子リスト、関数の引数リストなど、コンマ,は特定の文脈においてセパレータ(区切り文字)としても利用されるが、演算子としてのコンマとは完全に別物であるComma Operator: , | Microsoft Learn。たとえC系統であっても、JavaやC#を代表とする後発言語の多くはコンマ演算子をサポートせず、コンマ,にはセパレータとしての用法しかない。
使用例 以下の例ではC99規格で標準化されたコメント記法を使用しているが、コンマ演算子の動作仕様自体は従来のANSI C(C89)でも同様である。 int a=1, b=2, c=3, i; // このコンマは演算子としてではなくセパレータとして作用する。 i = (a, b); // 左オペランド a の値は読み捨てられるため、i には b の値が代入される。 // ... a=1, b=2, c=3, i=2
i = a, b; // i には a が代入される。つまり (i = a), b; と書くのと同値。 // ... a=1, b=2, c=3, i=1
i = (a += 2, a + b); // a に 2 を加算した後、a + b すなわち 3 + 2 を i に代入する。 // ... a=3, b=2, c=3, i=5
i = a += 2, a + b; // a に 2 を加算した後、a の値を i へ代入する。つまり (i = a += 2), a + b; と同値。 // ... a=5, b=2, c=3, i=5
i = a, b, c; // a の値を i に代入。 // ... a=5, b=2, c=3, i=5
i = (a, b, c); // c の値を i に代入。 // ... a=5, b=2, c=3, i=3
int j=0; j++, j++; // 左オペランドの評価に対する副作用完了後に右オペランドが評価されるため、未定義動作とはならない(j の値は 2 となる)。 (i, j) = 7; // C ではコンマ演算子の結果は右辺値であるためコンパイルできない。C++ では左辺値となるため問題ない(j の値は 7 となる)。
コンマ演算子の典型的な用途は、for文において複数の変数を扱うケースである。C99よりも前の規格では、for文の初期化節 (init-clause) および反復式 (iteration-expression) には式のみを書くことができるため、複数の変数を初期化したり、それらの値を増減させたりするときにコンマ演算子が使われる。 void doExampleOfCommaOperator(void) { int i, j; for (i = 0, j = 5; j > 0; ++i, j -= 2) { printf("i = %d, j = %d\n", i, j);
puts("Loop finished."); printf("i = %d, j = %d\n", i, j); }
int isSameString(const char* s1, const char* s2) { assert(s1 != NULL && s2 != NULL); for (; *s1 != '\0' && *s2 != '\0'; ++s1, ++s2) { if (*s1 != *s2) { return 0;
return *s1 == '\0' && *s2 == '\0'; }
C99以降はfor文の初期化節に宣言も書けるようになったが、複数の変数宣言におけるコンマは演算子ではなくセパレータである。 for (int i = 0, j = 5; j > 0; ++i, j -= 2) { printf("i = %d, j = %d\n", i, j);
なお、C++のfor文はCと構文仕様が若干異なるfor loop - cppreference.com (C)for loop - cppreference.com (C++)が、実質的な使い方は同じであり、本記事では詳細な説明は割愛する。
脚注
関連項目 CとC++の演算子