【C言語】演算子の種類と使い方・優先順位まとめ

この記事の要点

  • 算術演算子では代入は行われないが、インクリメント(デクリメント)では代入まで行われる
  • インクリメント(デクリメント)演算子は、前置きと後置きで処理順が変わる
  • 比較演算子や論理演算子は、主にif文などの条件判定で使われる

以前、C言語とはどんな言語か、またどんな業務で利用されるのかなど、基本を解説していました。

C言語での副業はなぜ難しい?業務の種類と必要なスキルからわかるその理由

C言語の中でも初心者の方にとってハードルが高いのが、演算子です。

C言語の演算子の種類はたくさんあり、初心者が全て覚えるのは困難です。

そこで当記事では、C言語の演算子の使い方をサンプルコード付きで丁寧に解説しています。

1記事でほとんどの演算子をカバーしているため、網羅的に演算子を学習することができます。

算術演算子とインクリメント・デクリメント演算子

「算術演算子」は、足し算や引き算などの計算を行うための演算子です。

「インクリメント演算子」「デクリメント演算子」は、足し算、引き算と代入を一度に行える演算子です。

それぞれ具体的に見ていきましょう。

算術演算子

演算子使用例説明
+a + ba に b を加えた結果を返す
-a - ba から b を引いた結果を返す
*a * ba に b をかけた結果を返す
/a / ba を b で割った結果を返す
%a % ba を b で割った余りを返す

以下はサンプルコードです。

int a = 5;
int b = 2;
printf("%d\n", a + b); // 7
printf("%d\n", a - b); // 3
printf("%d\n", a * b); // 10
printf("%d\n", a / b); // 2
printf("%d\n", a % b); // 1

printf("a : %d b : %d\n", a, b); // a : 5 b : 2

気を付けていただきたいのは、算術演算子を使っただけでは、aやbの値が変わっていないことです。

これは、算術演算子では、代入処理が行われていないからです。

インクリメント演算子、デクリメント演算子

演算子使用例説明
++a++, ++aa に 1 を加えた値を a に代入する(インクリメント)
--a--, --aa から 1 を引いた値を a に代入する(デクリメント)

サンプルコードは次のようになります。

int a = 5;
a++;
printf("%d\n", a); // 6
a--;
printf("%d\n", a); // 5

算術演算子と違うのは、計算結果の代入まで行われる点です。

インクリメントやデクリメントは、特にfor文内で使われることが多くあります。

for(int i = 0; i < 10; i++){
}

前置きと後置き

「++」や「--」を変数の前につける(前置き)か、後につける(後置き)かで、処理の順序が変わります。

使用例説明
前置き++a, --a他の処理より前にインクリメント(デクリメント)を行う
後置きa++, a--他の処理より後にインクリメント(デクリメント)を行う

説明だけだと理解しづらいと思うので、具体例を見ていきましょう。

// 前置き
int a1 = 5;
int b1 = ++a1;
printf("a1 : %d b1 : %d\n", a1, b1); // a1 : 6 b1 : 6
// 後置き
int a2 = 5;
int b2 = a2++;
printf("a2 : %d b2 : %d\n", a2, b2); // a2 : 6 b2 : 5

前置きの場合、b1への代入処理より前に、a1のインクリメントが行われるため、b1には加算後の「6」が代入されます。

一方、後置きの場合、b2への代入処理の後に、a2のインクリメントが行われます。

つまり、b2への代入処理の時点では加算されていないので、b2に「5」が代入されます。

代入演算子

「代入演算子」は、変数に値を代入するための演算子です。

算術演算子とセットになった、「複合代入演算子」も合わせてご紹介します。

演算子使用例説明
=a = ba に b を代入する
+=a += ba に a + b の計算結果を代入する
-=a -= ba に a - b の計算結果を代入する
*=a *= ba に a * b の計算結果を代入する
/=a /= ba に a / b の計算結果を代入する
%=a %= ba に a % b の計算結果を代入する

以下はサンプルコードです。

int a = 5;
int b = 2;

a += b;
printf("%d\n", a); // 7
a -= b;
printf("%d\n", a); // 5
a *= b;
printf("%d\n", a); // 10
a /= b;
printf("%d\n", a); // 5
a %= b;
printf("%d\n", a); // 1

複合代入演算子を使う度に、aの値が変化していることがおわかりいただけると思います。

比較演算子

「比較演算子」は、ある値どうしを比較したい場合に使います。

演算子使用例説明
<a < ba が b より小さければtrue、それ以外false
>a > ba が b より大きければtrue、それ以外false
<=a <= ba が b 以下ならtrue、それ以外false
>=a >= ba が b 以上ならtrue、それ以外false
==a == ba が b と等しいならtrue、それ以外false
!=a != ba が b と等しくないならtrue、それ以外false

以下はサンプルコードです。

int a = 0;
int b = 5;
while(true){
    if(a == b){
        break;
    }
    if(a < b){
        a++;
    }
}
printf("%d", a); // 5

aがbより小さい間、aをインクリメントし続け、aとbが等しくなったらループを脱出します。

このように、比較演算子はif文などの条件判定に使うことがほとんどです。

論理演算子

「論理演算子」は、論理値(true, false)の計算に使います。

演算子使用例説明
!!aaを否定する(aがtrueならfalse、falseならtrue)
&&a && ba、bの論理積(a、bが共にtrueならtrue、それ以外false)
||a || ba、bの論理和(a、bが共にfalseならfalse、それ以外true)

それぞれ、trueとfalseの組合せで次のような結果になります。

ab!aa && ba || b
truetruefalsetruetrue
truefalsefalsefalsetrue
falsetruetruefalsetrue
falsefalsetruefalsefalse

こちらも多くの場合、比較演算子と同様にif文などの条件分岐判定に使われます。

ビット演算子とシフト演算子

「ビット演算子」は、ビット単位での計算を行いたい場合に利用します。

「シフト演算子」は、ビットの桁移動を行いたい場合に利用します。

どちらも、メモリリソースが制限される、組み込み系プログラミングなどで利用されます。

しかし、かなりややこしい上に使う場面は限定的なので、初心者の方は必要になったときに勉強すれば十分です。

前項の論理演算子でも登場した記号(&、|)が使われていますが、全く別の演算なので混同しないよう注意してください

演算子使用例説明
&a & ba と b のビット単位の論理積
|a | ba と b のビット単位の論理和
^a ^ ba と b の排他的論理和
~~aa のビットパターンを反転
<<a << ba を b桁左シフト
>>a >> ba を b桁右シフト

以下はビット演算のコードサンプルです。

2進数の演算の知識が必要なため詳細な説明は割愛しますが、「|」を使うことで、flagという1つの変数に、flag1とflag3という2つのフラグを持たせています。

また、フラグがたっているかの判定に「&」を使っています。

short int flag1   = 0b0001;
short int flag2   = 0b0010;
short int flag3   = 0b0100;
short int flag4   = 0b1000;

short int flag = flag1 | flag3; // 0101
if((flag & flag1) != 0){
    puts("flag1");
}
if((flag & flag2) != 0){
    puts("flag2");
}
if((flag & flag3) != 0){
    puts("flag3");
}
if((flag & flag4) != 0){
    puts("flag4");
}

以下はシフト演算のサンプルです。

こちらも2進数の桁移動に関する理解が必要になりますが、「<>」を使って2のn乗分の1の計算を行っています。

算術演算子を使う場合より、高速に計算できます。

int num = 30;
num = num << 2; // 30 * 2の2乗
printf("%d\n", num); // 120
num = num >> 3; // 120 / 2の3乗
printf("%d", num); // 15

その他よく使う演算子

こちらでは、その他のよく使う演算子をご紹介します。

sizeof演算子

「sizeof演算子」は、型の大きさを調べるために使います。

演算子使用例説明
sizeofsizeof(a)a の型の大きさを返す

例えば、

sizeof(int)

と記述すると、多くの処理系では4が返って来ます。

これは、int型の変数には、メモリが4Byte割り当てられていることを意味します。

キャスト演算子

「キャスト演算子」は、明示的に型変換したい場合に利用します。

演算子使用例説明
(型名)(double)aa の型をdoubleに変換する

例えば、以下のサンプルをご覧ください。

int num1 = 5;
int num2 = 3;
double result = num1 / num2;

このようにすると、intどうしの割り算となり小数点以下が切り捨てられます。

結果、resultには、1.000…が入ります。

そこで、以下のようにキャストを使います。

double result = (double)num1 / num2;

こうすると、doubleとintの割り算になるため、小数点以下も有効となります。

resultには1.6666…が入ります。

演算子の優先順位

演算子には優先順位があります。

優先順位が高いものほど、先に評価されます。

例えば、

int num = 1 + 2 * 3;

とすると、「+」より「*」のほうが優先順位が高いため先に計算され、numには7が入ります。

当記事でご紹介した演算子の優先順位一覧は以下の通りです。

優先度演算子説明結合の向き
1++後置インクリメント左から右
--後置デクリメント
2!論理否定右から左
~ビット否定
++前置インクリメント
--前置デクリメント
sizeof型の大きさを取得
3(型名)キャスト右から左
4*掛け算左から右
/割り算
%剰余
5+足し算左から右
-引き算
6<<左シフト左から右
>>右シフト
7<左の方が小さい左から右
<=左は右以下
>左の方が大きい
>=左は右以上
8==等しい左から右
!=等しくない
9&ビット単位の論理積左から右
10^ビット単位の排他的論理和左から右
11|ビット単位の論理和左から右
12&&論理積左から右
13||論理和左から右
14=代入右から左
+=足し算 + 代入
-=引き算 + 代入
*=掛け算 + 代入
/=割り算 + 代入
%=剰余 + 代入

まとめ

C言語は演算子の数が多く、最初は覚えきれないと感じるかもしれません。

特に、「=」と「==」、「&」「|」と「&&」「||」を混同してしまうのは初心者あるあるなので、注意してください。

使っているうちに自然と身についていくので、焦らずじっくり取り組みましょう。

もし忘れてしまったら、その都度当記事を参照して、復習してみてください。

また、演算子と同じく初心者がC言語でつまずきやすいのが「ポインタ」です。

ポインタが難しいと感じている方や、ポインタの使い方やメリットがわからないという方に向けて、ポインタを効果的に習得する方法をご紹介しています。

初心者がC言語のポインタでつまずく3つの理由と理解するためのコツ

「ポインタ」と混同されやすい「配列」についても解説していますので、こちらも参考にしてください。

C言語での配列の使い方入門【初期化・コピー・定義・ポインタとの違い】