C言語:読みやすく、メンテナンスしやすいコードを書くための評価順序の重要性
演算子の優先順位
以下の表は、C言語の演算子の優先順位と結合方向を示しています。結合方向とは、同じ優先順位の演算子が複数ある場合に、式の評価方向を表します。
演算子グループ | 演算子 | 結合方向 |
---|---|---|
1 | () | なし |
2 | [] , . | 左から右 |
3 | ! , ~ , ++ , -- , - , + | 右から左 |
4 | * , / , % | 左から右 |
5 | + , - | 左から右 |
6 | < , > , <= , >= , == , != | 左から右 |
7 | && | 左から右 |
8 | ` | ` |
9 | = , += , -= , *= , /= | 右から左 |
10 | , | 左から右 |
例
以下の式における評価順序を矢印で示します。
a + b * c / d
a + (b * c) / d
a + ((b * c) / d)
同等の優先順位の演算子が複数ある場合は、結合方向に従って評価されます。
a - b + c
(a - b) + c
注意事項
- 副作用のある演算子は、評価順序によって結果が変わる可能性があります。
- 関数呼び出しは、式の評価前に完了します。
C11以降
C11以降では、一部の演算子の評価順序が明確に規定されています。
- 関数呼び出しの引数: 規定順序はありません。
- 代入演算子 (
=
,+=
,-=
,*=
,/=
): 右から左に評価されます。
例1:演算子の優先順位
この例では、演算子の優先順位に従って式が評価されます。
int result = 10 + 20 * 3;
この式は以下の順序で評価されます。
20 * 3
: 20 * 3 = 6010 + 60
: 10 + 60 = 70
よって、result
は 70 になります。
例2:結合方向
この例では、結合方向に従って式が評価されます。
int result = 10 - 5 + 3;
10 - 5
: 10 - 5 = 55 + 3
: 5 + 3 = 8
例3:関数呼び出し
この例では、関数呼び出しは式の評価前に完了します。
int add(int a, int b) {
return a + b;
}
int result = add(3, 4) * 5;
add(3, 4)
: add(3, 4) を呼び出し、7 を返す7 * 5
: 7 * 5 = 35
例4:副作用のある演算子
この例では、副作用のある演算子によって結果が変わる可能性があります。
int i = 1;
int result = i++ + i--;
i++
: i の値を 1 増やし、1 を返すi--
: i の値を 1 減らす
括弧を使用する
最も単純な方法は、括弧を使用して式を囲むことです。括弧内の式は、括弧の外側の式とは独立して評価されます。
int result = (10 + 20) * 3;
この式は、10 + 20
を先に評価し、その結果を 3
と掛けます。よって、result
は 90 になります。
変数を使用する
中間結果を一時的に変数に格納することで、評価順序を制御することができます。
int temp = 10 + 20;
int result = temp * 3;
この式は、10 + 20
の結果を temp
に格納し、その後 temp
を 3
と掛けます。よって、result
は 90 になります。
関数を使用する
関数を用いることで、式を論理的に分割し、評価順序を制御することができます。
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) {
return a * b;
}
int result = multiply(add(10, 20), 3);
この式は、add(10, 20)
を multiply(3)
の引数として渡します。よって、result
は 90 になります。
演算子の優先順位を変更する
C11以降では、一部の演算子の優先順位を変更する機能が導入されています。詳細は、以下の資料を参照してください。
注意事項
- 複雑な式の場合は、読みやすさやメンテナンス性を考慮して適切な方法を選択する必要があります。
- 上記の代替方法は、必ずしもすべての状況で有効とは限りません。
C言語における評価順序は、左から右に、演算子の優先順位に従って行われます。しかし、上記で紹介した代替方法を使用することで、状況に応じて評価順序を明示的に制御することができます。