カンマ演算子

せりか式 - C 言語チュートリアル - カンマ演算子

カンマ演算子

forループの初期化の時に利用しているカンマ(,)は、演算子の一種です。
ただし、演算子という名前を持っていますが、実際はステートメントの終わりを示すセミコロンとほぼ同様の機能も持っています。

カンマ演算子は、左から右に評価されます。カンマ演算子の返値は後の式の結果になります。

サンプル
    1: int a;
    2: a = -10, 0, 10; この場合、aには10が入ります。-10と0は読み捨てられます。(その都合上Warningが出るかもしれません)せんね。(追記 10/11/22)
    2: a = (-10, 0, 10); この場合、aに10が入ります。-10と0は読み捨てられます。(その都合上Warningが出るかもしれません)(追記 10/11/22)

C言語におけるステートメントはセミコロンまでが基本ですが、"どうしてもここで処理をしておきたい"、"マクロの関係上複数行にわたる処理を書くことができない"といったことがあると思います。

そのようなとき、カンマ演算子を使うことで1行で複数の処理をすることができます。
つまり、次の2つのプログラムは同じ実行結果となります。

プログラム1
    1:int a, b, c;
    2:
    3:a = 0;
    4:b = 1;
    5:c = 3;

プログラム2
    1:int a, b, c;
    2:
    3:a = 0, b = 1, c = 3;

例:if文での間違った使い方
ifはor(||)やand(&&)ではありません.

    1:if(0 <= a, a <= 10){// この判定文は,
    2: // 0 <= aの比較を行い,その結果を捨て,
    3: // a <= 10の比較を行い,その結果で分岐を行います
    4: // そのためこのブロックは,a <= 10の時に実行されます
    5:}

例:Swap マクロ
よくポインタの説明で使われるswap関数は次のような形をしています。

    1:void swap(int *a, int *b)
    2:{
    3:  a ^= b;
    4:  b ^= a;
    5:  a ^= b;
    6:}
となり、関数呼び出しは
    1:swap(&a, &b);
となります。
実際にはスワップ程度のことで、関数を呼び出していたのでは、プログラムのオーバーヘッドが大きくなり、あまり効率的ではありません。
(まあ、実際にはinline関数になり、関係ないとは思いますが...)
その上、ポインタを利用してるため、関数呼び出しに & が付きあまりスマートではありません。

そこで、カンマ演算子を用いて、スワップマクロを定義します。

    1:#define SWAP(x, y) ((x) ^= (y), (y) ^= (x), (x) ^= (y))
このマクロは1行でかかれているため、プログラム中では
    1:SWAP(a, b);
と書くだけで値の入れ替えが実現できます。

また、複数のことを同時に行いたいときに使うこともできます。

例: 出現頻度のカウント
次の文は a が 60以上であれば、countを1増やし、"合格"と表示します。

    1:puts(a >= 60 ? count += 1, "合格" : "不合格");

便利な演算子ですが、使いすぎると構文自体を破壊しかねないので、ほどほどにしておきましょう。
また、カンマはインクリメント・デクリメントの副作用完了点ではありません。
そのため、カンマ演算子の途中で、同じ変数に対してインクリメント・デクリメントを行うと値は不定となります。

例: インクリメント

    1:int i;
    2:
    3:i = 0;
    4:i++;
    5:i++;
    6:/* この時点で i は 2 である */
    7:
    8:i++, i++;
    9:/* 直前の行で1行のあいだに、複数回インクリメントをしているため、i の値は不定となってしまっている */
   10:/* 値が不定となるのをさけるため、"i++, i++;" を "i+=1, i+=1;" とするとこの時点での i は 4 となる */


トップへ