評価順序
From cppreference.com
C言語のあらゆる演算子のオペランドの評価順序は、関数呼び出し式の関数引数の評価順序、およびあらゆる式内の部分式の評価順序を含め、未規定です(下記に記載されている場合を除く)。コンパイラは任意の順序でそれらを評価し、同じ式が再度評価される際に別の順序を選択する可能性があります。
C言語には、左から右または右から左への評価という概念はありません。これは、演算子の左から右および右から左への結合性と混同してはなりません。式 f1() + f2() + f3() は、演算子+の左から右への結合性のため、(f1() + f2()) + f3() と解析されますが、f3 への関数呼び出しは、実行時に最初、最後、または f1() と f2() の間に評価される可能性があります。
目次 |
[編集] 定義
[編集] 評価
コンパイラが各式または部分式に対して実行する評価には、2つの種類があります(どちらも任意です)
- 値の計算: 式が返す値の計算。これには、オブジェクトの識別(左辺値評価)の決定、またはオブジェクトに以前に割り当てられた値の読み取り(右辺値評価)が含まれる場合があります。
- 副作用: volatile 左辺値によって指定されたオブジェクトへのアクセス(読み取りまたは書き込み)、オブジェクトへの変更(書き込み)、アトミックな同期(C11以降)、ファイルの変更、浮動小数点環境の変更(サポートされている場合)、またはそれらの操作のいずれかを実行する関数の呼び出し。
式によって副作用が生成されず、コンパイラがその値が使用されないと判断できる場合、その式は評価されないことがあります。
[編集] 順序付け
"sequenced-before" は、同じスレッド内の評価間の非対称で推移的な対の関係です(アトミック型とメモリバリアが関与する場合、スレッドをまたぐことがあります)。
- 部分式E1とE2の間にシーケンスポイントが存在する場合、E1の値計算と副作用の両方は、E2のすべての値計算と副作用の前にsequenced-beforeされます。
|
(C11 以降) |
[編集] 規則
1) すべての関数引数と関数指定子の評価の後、実際の関数呼び出しの前にシーケンスポイントがあります。
2) 以下の二項演算子
&& (論理AND)、 || (論理OR)、および , (カンマ) の最初の(左)オペランドの評価の後、2番目の(右)オペランドの評価の前にシーケンスポイントがあります。3) 条件演算子
?: の最初の(左)オペランドの評価の後、2番目または3番目のオペランド(どちらが評価されるか)の評価の前にシーケンスポイントがあります。|
5) 完全な宣言子の最後にシーケンスポイントがあります。
6) ライブラリ関数の戻りの直前にシーケンスポイントがあります。
|
(C99以降) |
|
9) 任意の演算子のオペランドの値計算(副作用は除く)は、演算子の結果の値計算(副作用は除く)の前にシーケンスされます。
10) 直接代入演算子とすべての複合代入演算子の副作用(左引数の変更)は、左右両引数の値計算(副作用は除く)の後にシーケンスされます。
11) 後置インクリメントおよび後置デクリメント演算子の値計算は、その副作用の前にシーケンスされます。
12) 他の関数呼び出しの前にシーケンスされておらず、後にシーケンスされていない関数呼び出しは不確定にシーケンスされます(異なる関数呼び出しを構成するCPU命令は、関数がインライン化されている場合でもインターリーブできません)。
13) 初期化リスト式では、すべての評価は不確定にシーケンスされます。
14) 不確定にシーケンスされた関数呼び出しに関して、複合代入演算子の操作、およびインクリメントおよびデクリメント演算子の前置形と後置形の両方は、単一の評価です。 |
(C11 以降) |
[編集] 未定義の動作
1) スカラーオブジェクトに対する副作用が、同じスカラーオブジェクトに対する別の副作用に対して順序付けられていない場合、動作は未定義です。
i = ++i + i++; // undefined behavior i = i++ + 1; // undefined behavior f(++i, ++i); // undefined behavior f(i = -1, i = -1); // undefined behavior
2) スカラーオブジェクトに対する副作用が、同じスカラーオブジェクトの値を使用する値計算に対して順序付けられていない場合、動作は未定義です。
f(i, i++); // undefined behavior a[i] = i++; // undefined bevahior
3) 上記の規則は、部分式の少なくとも1つの許容される順序付けが、そのような順序付けられていない副作用を許容する限り適用されます。
[編集] 関連項目
演算子の優先順位:ソースコード表現から式がどのように構築されるかを定義します。
| C++ ドキュメント(評価の順序について)
|