第6章 コンマ演算子

 今まで、いろいろな演算子について話してきました。今回は一風変わった演算子について話してみようと思います。


 では、今回の要点です。


 では、いってみましょう。


 前回のプログラムの for 文をもう一度見てみましょう。

for(i = 0; i < 8; i++)
{
    if(fscanf(pf1, "%d", &num1) == EOF ||
    fscanf(pf2, "%d", &num2) == EOF)
    {
        fputc('\n', pf3);
        goto LAST;
    }

    fprintf(pf3, "%d ", num1 + num2);
    nNumbers++;
}

 最後に nNumbers++; というのがありますね。しかしこれ、感覚的には for 文の i++ のところに入れてしまいたい気もします。ところが、for 文のループ文(i++ のあるところ)には文は1つしか置けません。

 では、これは叶わぬ願いなのでしょうか? それは違います。ここでコンマ演算子というものを使えば、それは実現できます。「コンマ演算子」と大層な名前がついていますが、何て事はない、ただの , です。

for(i = 0; i < 8; i++, nNumbers++)
{
    if(fscanf(pf1, "%d", &num1) == EOF ||
    fscanf(pf2, "%d", &num2) == EOF)
    {
        fputc('\n', pf3);
        goto LAST;
    }

    fprintf(pf3, "%d ", num1 + num2);
}

 このように、コンマで区切れば全体で1文と判断されるようになるのです。


 しかし、これはコンマ演算子の応用法であって、その真の意味を表してはいません。コンマ演算子の真の意味は、次のようなものです。

a = (b, c);

 ...何だか座標を代入しているような感じですね。このとき、b, c の値は c になります。そして、その型は c の型になります。b の型は何でも構いません。これがコンマ演算子の真の意味です。

 つまり、ここでは a には c の値が代入されるのです。カッコでくくっているのは、ただ単にコンマ演算子の優先順位は異常に低いからです。

 そして、代入などを行わないのであれば、別に c が値でなくても構いません。つまり、戻り値の型が void の関数を c にもってきても構わないのです。

 また、b に関数などがあると、それはもちろん実行されます。b を完全に無視するのではなく、その値だけを無視するわけです。


 コンマ演算子の利用法として多いのが、上でやった for 文での利用法でしょう。初期化文を2つにするというのにも使うことがあります。

 上の説明から、<式1>, <式2> も になることが分かります。

 宣言文とブロック文(ブロックも文と見なします)を除けば、文はただ式にセミコロンをつけただけのものです。戻り値の型が void の関数を呼ぶという文であってもそうです。なので、セミコロンを除いた文をコンマで繋げば、あとはこれにセミコロンをつけると全体で1文になるということが分かるでしょう。


 そして、他にも while 文での利用法があります。例えば、ある変数にある関数から値を代入し、さらにその値をループの条件にしたいというときがあるでしょう。それは、ファイル操作などでよく起こります。

 例えば、ファイルから1バイトずつ読み出していき、その値を元に何か処理をしたいと思います。すると、コンマ演算子を使わなければ次のようになります。

while(1)
{
    letter = fgetc(pf);
    if(letter == EOF)
        break;

    ... 処理 ...
}

 fgetc はファイルから1バイト読み出す関数です。ファイルの終わりに達したとき、またはエラーが出たときには EOF が返されます。

 ファイルの終わりに達するとループを終わるわけですが、while 文は無限ループにしてあります。これでは while 文の意義があまりないような気がします。

 かといって、この条件を while 文のカッコに書いてしまうと、次のように fgetc をもう1個書くことになります。これでは無駄な気がします。

letter = fgetc(pf);
while(letter != EOF)
{
    ... 処理 ...

    letter = fgetc(pf);
}

 そこでコンマ演算子の登場です。

while(letter = fgetc(pf), letter != EOF)
{
    ... 処理 ...
}

 while 文のカッコの中は次のようになっています。

letter = fgetc(pf), letter != EOF

 先ずは letter = fgetc(pf) が実行されます。これでファイルから1バイト読み出されます。

 そして、次に letter != EOF が実行されます。条件式は真か偽かを返す式です。そして、条件式がコンマ演算子の後に来ているので、while 文のカッコの中の値はこの条件式の値になります。

 つまり、ループの条件は letter != EOF になります

 こうすれば、while 文を活かしつつ fgetc が1つですむようになります。


 コンマ演算子はやたらめったら使うとプログラムが分かりにくくなります。しかし、有効に使えばプログラムは分かりやすく、さらにきれいになります。この辺は goto 文と似たところがありますね。

 マイナーな響きのあるコンマ演算子ですが、有効に利用してやって下さい。


 では、今回の要点です。


 次回は a = b = 0; のようなことをやります。それでは。


第5章 飛んでいきな | 第7章 代入文のリサイクル

Last update was done on 2000.8.5

この講座の著作権はロベールが保有しています