C 演算子の優先順位と結合性は、式のオペランドのグループ化と評価に影響します。 演算子の優先順位は、優先順位の高い演算子または低い演算子が存在する場合にのみ意味があります。 優先順位の高い演算子を持つ式が最初に評価されます。 優先順位は、"binding" という単語で記述することもできます。優先順位の高い演算子は、バインディングが厳密であると言われます。
次の表は、C 演算子の優先順位と結合規則 (オペランドが評価される順序) をまとめたものであり、優先順位が最も高いものから最も低い順に一覧表示されています。 複数の演算子が一緒に表示される場合は、優先順位が等しく、結合性に従って評価されます。 表の演算子については、 後置演算子で始まるセクションで説明します。 このセクションの残りの部分では、優先順位と結合性に関する一般的な情報を提供します。
C 演算子の優先順位と結合性
| 記号 1 | 操作の種類 | 結合規則 |
|---|---|---|
[
]
(
)
.
->
++
-- (後置) |
表現 | 左から右 |
sizeof
&
*
+
-
~
!
++
-- (プレフィックス) |
単項演算子 | 右から左 |
| typecasts | 単項演算子 | 右から左 |
*
/
%
|
乗法 | 左から右 |
+
-
|
加法 | 左から右 |
<<
>>
|
ビットごとのシフト | 左から右 |
<
>
<=
>=
|
リレーショナル | 左から右 |
==
!=
|
平等 | 左から右 |
& |
Bitwise-AND | 左から右 |
^ |
ビットごとの排他的 OR | 左から右 |
| |
ビットごとの包括 OR | 左から右 |
&& |
Logical-AND | 左から右 |
|| |
Logical-OR | 左から右 |
? : |
条件式 | 右から左 |
=
*=
/=
%=
+=
-=
<<=
>>=
&=
^=
|=
|
単純代入と複合代入 2 | 右から左 |
, |
順次評価 | 左から右 |
1 演算子は、優先順位の降順で一覧表示されます。 複数の演算子が同じ行またはグループに表示される場合、それらの演算子の優先順位は同じです。
2 すべての単純代入演算子と複合代入演算子の優先順位が等しい。
式には、優先順位が等しい複数の演算子を含めることができます。 このような演算子が 1 つの式で同じレベルに出現する場合、演算子の結合性に従って、右から左、または左から右に評価が進みます。 評価の方向は、同じレベルで複数の乗算 (*)、加算 (+)、またはバイナリ ビットごとの (&、 |、または ^) 演算子を含む式の結果には影響しません。 操作の順序は言語によって定義されません。 コンパイラが一貫性のある結果を保証できる場合、コンパイラはこのような式を任意の順序で自由に評価できます。
順次評価 (,)、論理 AND (&&)、論理 OR (||)、条件式 (? :)、関数呼び出し演算子のみがシーケンス ポイントを構成するため、オペランドの特定の評価順序が保証されます。 関数呼び出し演算子は、関数識別子に続くかっこのセットです。 順次評価演算子 (,) は、オペランドを左から右に評価することが保証されます。 (関数呼び出しのコンマ演算子は、順次評価演算子と同じではなく、そのような保証を提供しません)。詳細については、「 シーケンス ポイント」を参照してください。
論理演算子は、左から右へのオペランドの評価も保証します。 ただし、式の結果を決定するために必要なオペランドの最小数を評価します。 これは"短絡"評価と呼ばれます。 したがって、式の一部のオペランドは評価されない場合があります。 たとえば、式では
x && y++
2 番目のオペランド ( y++) は、 x が true (0 以外) の場合にのみ評価されます。 したがって、xが false (0) の場合、yはインクリメントされません。
例示
次の一覧は、コンパイラが複数のサンプル式を自動的にバインドする方法を示しています。
| 表現 | 自動バインド |
|---|---|
a & b || c |
(a & b) || c |
a = b || c |
a = (b || c) |
q && r || s-- |
(q && r) || s-- |
最初の式では、ビットごとの AND 演算子 (&) は論理 OR 演算子 (||) よりも優先順位が高いので、 a & b は論理 OR 演算の最初のオペランドを形成します。
2 番目の式では、論理 OR 演算子 (||) は単純代入演算子 (=) よりも優先順位が高いので、 b || c は代入の右側のオペランドとしてグループ化されます。
aに割り当てられる値は 0 または 1 であることに注意してください。
3 番目の式は、予期しない結果を生成する可能性がある正しい形式の式を示しています。 論理 AND 演算子 (&&) は論理 OR 演算子 (||) よりも優先順位が高いので、 q && r はオペランドとしてグループ化されます。 論理演算子は左から右へのオペランドの評価を保証するため、 q && r は s--前に評価されます。 ただし、 q && r が 0 以外の値に評価された場合、 s-- は評価されず、 s はデクリメントされません。
sをデクリメントしないとプログラムで問題が発生する場合は、s--を式の最初のオペランドとして使用するか、別の演算でsデクリメントする必要があります。
次の式は無効であり、コンパイル時に診断メッセージを生成します。
| 無効な式 | 既定のグループ化 |
|---|---|
p == 0 ? p += 1: p += 2 |
( p == 0 ? p += 1 : p ) += 2 |
この式では、等値演算子 (==) の優先順位が最も高いため、 p == 0 はオペランドとしてグループ化されます。 条件式演算子 (? :) の優先順位が次に高くなります。 最初のオペランドは p == 0、2 番目のオペランドは p += 1。 ただし、条件式演算子の最後のオペランドは、p += 2ではなくpと見なされます。このpの出現は、複合代入演算子よりも条件式演算子に密接にバインドされるためです。
+= 2に左側のオペランドがないため、構文エラーが発生します。 この種のエラーを防ぎ、より読みやすいコードを生成するには、かっこを使用する必要があります。 たとえば、次に示すようにかっこを使用して、前の例を修正して明確にできます。
( p == 0 ) ? ( p += 1 ) : ( p += 2 )