プログラミング言語C/C++およびJavaScriptなどにおけるコンマ演算子(コンマえんざんし、: comma operator)は、左オペランド(被演算子)を評価しそのを捨て、その後右オペランドを評価する演算子である。コンマの記号文字「,」が使用される。順次演算子(じゅんじえんざんし)もしくは順次評価演算子 (sequential-evaluation operator) と呼称されることもある[1][2][3]日本産業規格(旧称:日本工業規格)のJIS X 3010:2003『プログラム言語C』およびJIS X 3014:2003『プログラム言語C++』では「コンマ演算子」と表記されている。「カンマ演算子」と表記されているドキュメントもある[4][5]

コンマ演算子の値とは右オペランドの値と型となる。Cでは右辺値だが、C++では右オペランドが左辺値であれば左辺値となる。また、左オペランドの評価に対する副作用(C++では一時変数の破棄を除く)が完了した後に右オペランドが評価されることが規格上保証されている。コンマ演算子の優先順位は最も低く規定されている[6][7]。代入演算子=よりも低いため、例えばコンマ演算子の評価結果(右オペランド)を何らかの変数に代入したい場合は、括弧で囲んでx = (a, b);のように書く必要がある。

複数の変数の宣言、配列構造体の初期化子リスト、関数の引数リストなど、コンマ,は特定の文脈においてセパレータ(区切り文字)としても利用されるが、演算子としてのコンマとは完全に別物である[8]。たとえC系統であっても、JavaC#を代表とする後発言語の多くはコンマ演算子をサポートせず、コンマ,にはセパレータとしての用法しかない。

使用例

編集

以下の例では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と構文仕様が若干異なる[9][10]が、実質的な使い方は同じであり、本記事では詳細な説明は割愛する。

脚注

編集
  1. ^ 平林雅英『ANSI C言語辞典』(初版)技術評論社、1989年10月25日、351頁。ISBN 4-87408-320-X 
  2. ^ Sequential-Evaluation Operator | Microsoft Learn
  3. ^ 順次評価演算子
  4. ^ カンマ演算子 - RAD Studio
  5. ^ カンマ演算子 (,) - JavaScript | MDN
  6. ^ C Operator Precedence - cppreference.com
  7. ^ C++ Operator Precedence - cppreference.com
  8. ^ Comma Operator: , | Microsoft Learn
  9. ^ for loop - cppreference.com (C)
  10. ^ for loop - cppreference.com (C++)

関連項目

編集