意味規則 コンマ演算子は,左オペランドをボイド式として評価する。その評価の直後を副作用完了点とする。次に右オペランドを評価する。コンマ演算子の結果は,右オペランドの型及び値を持つ*1。コンマ演算子の結果を変更するか,または次の副作用完了点の後でそれにアクセスしようとした場合,その動作は未定義とする。
代入式を並べることで,コンマ演算子を用いたときとほぼ同じ動作を実現できるので,コンマ演算子はあまり使われない。
#include <stdio.h> int main(void){ int a = 0; a = 10; a = 20; printf("%d\n", a); // 3つの代入式の並び a = 10, a = 20, printf("%d\n", a); // コンマ演算子の使用で1つの式 }
20 20
しかし,代入式を並べることが出来ない箇所ではコンマ演算子が活躍する。代入式を並べることが出来ない代表的な箇所は,繰り返し文の制御式と,for文の節1,式3である。
#include <stdio.h> int main(void){ int i, j; for (/*節1*/i = 0, j = 9; i < j; /*式3*/++i, --j){ printf("%d %d\n", i, j); } while (/*条件式*/printf("%d ", i), i){ --i; } }
0 9 1 8 2 7 3 6 4 5 5 4 3 2 1 0
また,コンマ演算子とコンマ区切り子は文法上別のものとして扱われる。初期化子並びや実引数式並びに現れるコンマは区切り子である。それらの文脈でコンマ演算子を用いるには括弧を使う。
#include <stdio.h> int main(void){ printf("%d\n", (0, 1, 2)); }
2
本来であればコンマ演算子の結果は左辺値ではなく評価した値を返すが,左辺値を返す実装も存在する*2。しかし,その結果(左辺値)を変更すること,またそれにアクセスすることは結局のところ未定義動作となる。
#include <stdio.h> int main(void){ int a = 3, b = 5; (a, b) = 7; // コンマ演算子の結果を変更しようとしている printf("b = %d\n", b); // コンマ演算子の結果にアクセスしている }
gccやdmcでは上記コードでコンパイルが通るが,プログラム言語Cにおいて全く移植性のないコードなので普通用いるべきではない。(gccでは警告を出す。)未定義動作のコードなのでサンプル出力も挙げない。