C言語プログラミングを使いこなすには、演算子の仕様を理解することが必要不可欠です。
本記事では、C言語で使用される主要な演算子とその優先順位について詳しく解説します。
演算子の優先順位とは?
プログラミングにおいて、演算子の優先順位とは、複数の演算子が含まれる式を評価する際に、どの演算子を優先して計算するかを決めるルールです。
例えば、「2 + 3 * 4」という式があった場合、掛け算が先に行われます。つまり、「3 * 4」が最初に計算され、「2 + (3 * 4)」となります。
このような優先順位はプログラム言語ごとに定義されています。
C言語では以下のような優先順位があります。
優先度 | 演算子 | 説明 |
---|---|---|
1 | () | 括弧 |
2 | ++ -- | 前置インクリメント・デクリメント |
2 | ! ~ | 論理否定・ビット反転 |
2 | ++ -- | 後置インクリメント・デクリメント |
2 | + - | 単項プラス・マイナス |
2 | * & sizeof | ポインタ・サイズ取得 |
3 | * / % | 乗除算・剰余算 |
4 | + - | 加算・減算 |
5 | << >> | シフト演算子 |
6 | <<= >>= | 比較演算子 |
7 | == != | 等価・不等価比較演算子 |
8 | & | ビット積 AND 演算子 |
9 | | | ビット和 OR 演算子 |
10 | ^ | 排他的ビット和 XOR 演算子 |
11 | && | 論理積 AND 演算子 |
12 | || | 論理和 OR 演算子 |
13 | ? : | 三項演算子 |
14 | = += -= *= /= %= &= ^= |= <<= >>= | 代入 |
これらの規則に従って評価されることで、正しい結果を得ることが出来ます。
ただし、可読性や保守性を考慮したコード作成では明示的な括弧付けも重要です。
基本演算子の優先順位
基本演算子の優先順位
C言語において、演算子は優先順位が決まっています。つまり、複数の演算子が含まれる式を評価する場合には、どの演算子から処理すべきかという順序があらかじめ定義されています。
単項演算子(++ — + – ! ~)
()に次いで最も優先度が高いのは単項演算子・二項演算子です。
この中でも++や–など後置型のインクリメント・デクリメント演算子は非常によく使われます。
次に、+や-など符号を表す単項プラス・マイナス演算子や、真偽値を反転させる!(否定)やビット反転する~(ワンズコンプリメント)なども含まれます。
例えば以下のような式では、「a」変数に1を加えた後、「b」変数から1を引いた結果と「c」変数自身の値を掛けた結果が出力されます。
int a = 5;
int b = 3;
int c = 2;
printf("%d", ++a * (b-- - c));
上記式で実行した場合、「a」変数に対して前置型インクリメント(++a)で1加えられた後、b - c
を行い、6 * ( 3 -2)
が計算されて6
が出力されます。
最後にbが後置インクリメントされてb
が4
になります。
算術演算子(*, /, %, +, -)
算術演算子は、算術演算子間で優先順位に差があります。
算術演算子の中で優先順位が高いのが乗除剰余(* / %)で、その後に加減(+ -)演算子が評価されます。
これらはプログラミングに関わらず、小学校で習った四則計算の優先順位と同等です。
例えば以下のような式では、y * xが計算されたあとに足し算と引き算が行われます。
int x = 4;
int y = 2;
// x + (y * x) - y の形で計算される
printf("%d", x + y * x - y);
上記の計算式では乗算が最も優先順位が高いため、x + y
ではなくy * x
が先に処理されます。
関係演算子の優先順位
関係演算子は、比較を行うための演算子ですが、関係演算子同士で優先順位に差があります。。
<、<=、>、>=
これらの演算子は同じ優先順位であり、左から右へと評価されます。
ほかの関係演算子 ==
!=
があった場合、==
!=
よりも優先的に処理されます。
==、!=
これらの演算子は同じ優先順位であり、左から右へと評価されます。
ほかの関係演算子 <
<=
>
>=
があった場合、==
!=
よりが後に処理されます。
以上が関係演算子の優先順位です。次の節では論理演算子の優先順位について説明します。
シフト(<< >>) の結合規則と優先度
シフト演算子は、ビット単位での左右シフトを行うために使用されます。
左シフト演算子(<<)は、指定された数値分だけビットを左に移動させます。同様に、右シフト演算子(>>)は、指定された数値分だけビットを右に移動させます。
C言語では、シフト演算子の優先順位は算術演算より低いです。
また、シフト演算子自身の結合規則も重要です。
シフト演算子は、左から右へ評価するため、「<<」および「>>」演算子は左結合性を持ちます。
以下の例を見てみましょう。
int a = 8, b = 2;
int c = a << b >> 1;
この場合、「a << b」という式が最初に評価されるため、「a」変数内の値である8が2ビット分だけ左側に移動して32になります。
その後、「b >> 1」という式が評価されるため、「b」変数内の値である32が1ビット分だけ右側に移動して16になります。
そして、最終的にcに代入される値は16となります。
ビット単位論理積・和・排他的論理和(& | ^) の結合規則と優先度
ビット単位論理積・和・排他的論理和(& | ^) は、ビット演算子の一種であり、2進数表記された数値の各桁を比較して計算する演算子です。
これらの演算子には結合規則と優先度があります。
結合規則
ビット単位論理積・和・排他的論理和(& | ^) の結合規則は、左から右へと順番に処理されます。同じ演算子同士であれば左側から順番に計算されます。
a & b & c & d
優先度
ビット単位論理積・和・排他的論理和(& | ^) の優先度は以下の通りです。
優先度 | 演算子 | 説明 |
---|---|---|
1 | ~ | NOT |
2 | & | AND |
3 | ^ | XOR |
4 | | | OR |
例えば、「~」が最も優先度が高く、「|」が最も低いです。したがって、「&」や「^」を組み合わせて式を書く場合、括弧で囲んで明示的に優先順位を指定しないと想定外の順序で演算される可能性があります。
論理演算子の優先順位
論理演算子には、AND(&&)、OR(||)、NOT(!)があります。これらの演算子を組み合わせて条件式を作成することができます。
論理演算子の優先順位は、NOT!
が最も高く、次にAND&&
、最後にOR||
です。
つまり、NOT > AND > OR の順番で評価されます。
例えば、「a && b || c
」という式があった場合、「a && b
」が先に評価され、「c
」とORで結合されるため、「(a && b) || c
」と同じ意味になります。
また、括弧を使って明示的に優先度を指定することもできます。
「(a || b) && (c || d)」といった形で書くことで、「a OR b」と「c OR d」の両方の条件を満たしていたら真となるように評価されます。
優先順位の理解はC言語プログラミングを効率的に行う上で役立ちますが、可読性やヒューマンエラーを防止するためにも、優先順位をわかっていたとしても括弧付けを行ってうっかりミスを減らすことがおすすめです。
条件演算子(?:)の優先順位
条件演算子(?:)は、三項演算子とも呼ばれます。この演算子は、if-else文を簡潔に表現するために使用されます。
例えば、以下のようなコードがある場合、
int a = 10;
int b;
if (a > 5) {
b = 1;
} else {
b = 0;
}
これを条件演算子で書き換えると、
int a = 10;
int b = (a > 5) ? 1 : 0;
となります。
条件演算子の優先順位は比較的低く、他の多くの演算子よりも後ろに位置します。そのため、括弧で囲むことが推奨されています。
例えば、
int x = (a > b) ? c + d : e - f * g;
この式では、まずa > b
が評価され、true
であればc + d
が、false
であればe - f * g
が代入されます。
また、「? :」演算子は右結合性を持ちます。つまり、
x = (a > 0) ? b : c ? d : e;
この式では、c ? d : e
という部分から評価されていきます。
c
が真であればd
が返り、偽であればe
となります。最終的に、
aが0以上であればbがxに代入され、aが0未満ならc ? d : e
の結果が代入されます。
条件演算子?:
は非常に便利な機能ですが、優先順位や右結合性を理解しないとバグの原因に繋がるほか、可読性も落ちるのでif-else
と?:
を上手く使い分けるようにしましょう。
代入演算子の優先度
代入演算子は、変数に値を代入するための演算子です。C言語では、代入演算子が最も低い優先度を持ちます。つまり、他の演算子よりも後に評価されます。
例えば、a = b + c
という式があった場合、まずb + c
が評価されてから、a
に結果が代入されます。
これは+
演算子の方が=
演算子よりも高い優先度を持っているため、b + c
が先に評価されることになります。
また、複合代入演算子+=
-=
*=
/=
やビット単位の論理和・積などを行う複合ビット単位代入演算子|=
&=
^=
も同様に最低優先度で評価されます。
カンマ(,) の結合規則と使用方法
C言語プログラミングでそれなりに使用するカンマも、実は演算子の一つです。
カンマ演算子は、複数の式を一つにまとめるために使用されます。この演算子は、左から右へ評価されます。
例えば、以下のようなコードがあった場合、
int a = 1, b = 2, c = 3;
これは、「a=1」、「b=2」、「c=3」という3つの代入文をカンマで区切って1行で書いています。
また、関数呼び出し時にもカンマ演算子が使われることがあります。例えば、
printf("%s %s","Hello","World!");
この場合、「Hello, world!」という文字列が表示されます。
ただし、カンマ演算子は可読性を損なう可能性もあるため、適切な使用方法に留意する必要があります。