C言語の演算子とは ~演算子の種類と優先順位~

C言語

演算子とは、変数や定数の操作、計算を行うための記号です。演算子には優先順位があり、変数の左右どちらに記述するかによって意味が変わるなど、よく使うものではありますが、使い方に注意が必要です。この記事では、主な演算子の種類とその使い方を解説し、演算が行われる際の優先順位について解説します。

1.演算子の種類

演算子には多くの種類があり、演算子を使用すると変数や定数に対してさまざまな演算を行うことができます。

1-1.演算子一覧

本記事で解説するC言語の演算子を表1にまとめました。演算子を使用する際の参考にしてください。

演算子の種類 演算子
算術演算子 +,-,*,/,%,
インクリメント/デクリメント演算子 ++,–
比較演算子 >,>=,<,<=,==,!=
論理演算子 !,&&,||
ビット/シフト演算子 ~,&,|,^,<<,>>
代入演算子 =,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=

1. 演算子一覧

1-2.算術演算子

算術演算子は、2つの値の加算、減算、乗算、除算の四則演算と除算の余りを求める剰余算を行うための演算子です。表2は算術演算子の一覧です。

演算子 記述例 説明
+ a + b 加算
a – b 減算
* a * b 乗算
/ a / b 除算
% a % b 剰余算

2. 算術演算子一覧

算術演算子を使って演算を行う例を以下に示します。

#include 

int main(void){
    int a, b, ans;

    a = 7;
   b = 2;

    ans = a + b;
    printf(“%d\n”, ans);

    ans = a - b;
    printf(“%d\n”, ans);

    ans = a * b;
    printf(“%d\n”, ans);

    ans = a / b;
    printf(“%d\n”, ans);

    ans = a % b;
    printf(“%d\n”, ans);

    return 0;
}

実行結果は以下の通りです。

9
5
14
3
1

除算の結果が3となっていることに注意してください。int型どうしで演算を行うと結果もint型となり、小数点以下が切り捨てられて整数になります。

1-3.インクリメント/デクリメント演算子

インクリメントとは値に1を加算すること、デクリメントとは値から1を減算することです。インクリメント/デクリメント演算子はfor文やwhile文で繰り返し行う処理を記述する場合などに使用されます。表3はインクリメント/デクリメント演算子の一覧です。

演算子 記述例 説明
++ ++a,a++ インクリメント(1加算する)
–a,a– デクリメント(1減算する)

3. インクリメント/デクリメント演算子一覧

変数の前に演算子を記述する場合を前置、後に演算子を記述する場合を後置と呼びます。前置と後置による違いは後述します。

インクリメント/デクリメント演算子を使って演算を行う例を以下に示します。

#include 

int main(void){
    int a, b, ans;

    a = 7;
    b = 2;

    ans = ++a;
    printf(“%d,%d\n”, ans, a);

    ans = --b;
    printf(“%d,%d\n”, ans, b);

    ans = a++;
    printf(“%d,%d\n”, ans, a);

    ans = b--;
    printf(“%d,%d\n”, ans, b);

    return 0;
}

実行結果は以下の通りです。

8,8
1,1
8,9
1,0

前置と後置では演算の順番が変わります。前置でも後置でも最終的にインクリメント/デクリメントが行われますが、前置の場合は先にインクリメント/デクリメントをしてから代入、後置の場合は先に代入をしてからインクリメント/デクリメントが行われます。

1-4.比較演算子

比較演算子は、2つの値を比較するための演算子です。関係演算子とも呼ばれます。表4は比較演算子の一覧です。

演算子 記載例 説明
> a > b aはbより大きい
>= a >= b aはb以上
< a < b aはbより小さい
<= a <= b aはb以下
== a == b aはbと等しい
!= a != b aはbと等しくない

4. 比較演算子一覧

比較演算子を使って演算を行う例を以下に示します。

#include 

int main(void){
int a, b;

a = 5;
b = 1;

if(a > 1) printf("TRUE\n");

if(b <= 1) printf("TRUE\n");

if(a == 5) printf("TRUE\n");

if(b != 5) printf("TRUE\n");

return 0;
}

実行結果は以下の通りです。

TRUE
TRUE
TRUE
TRUE

左右が等しいことを示す比較演算子が「=」ではなく、「==」であることに注意してください。

1-5.論理演算子

論理演算子は、条件式のNOT(否定)AND(論理積)OR(論理和)を得るための演算子です。表5は論理演算子の一覧です。

演算子 記載例 説明
! !a NOT(論理否定)
&& a && b AND(論理積)
|| a || b OR(論理和)

5. 論理演算子一覧

論理演算子を使って演算を行う例を以下に示します。

#include 

int main(void){
int a, b;

a = 5;
b = 1;

if(!(a < 1)) printf("TRUE\n");

if(1 < a && a < 10) printf("TRUE\n");

if(1 < a || 1 < b) printf("TRUE\n");

return 0;
}

実行結果は以下の通りです。

TRUE
TRUE
TRUE

1番目の条件式「a < 1」を「()」で囲んでいますが、これは演算子の優先順位によるものです。「()」で囲わずに「!a < 1」と記述すると、「!a」の論理演算が先に行われ、その結果と「< 1」の比較演算が行われます。演算子の優先順位については後述します。

1-6.ビット/シフト演算子

ビット演算子は値を2進数(0, 1のビット列)とみなして論理演算を行うための演算子、シフト演算子は値を2進数とみなしてビットを左右に移動させる(シフト演算)ための演算子です。表6はビット/シフト演算子の一覧です。

演算子 記述例 説明
~ ~a NOT(ビット反転)
& a & b AND(ビット論理和)
| a | b OR(ビット論理積)
^ a ^ b XOR(ビット排他的論理和)
<< a << b (bビット)左シフト
>> a >> b (bビット)右シフト

6. ビット/シフト演算子一覧

ビット/シフト演算子を使って演算を行う例を以下に示します。

#include 

int main(void){
int a, b, ans;

a = 2;
b = 3;

ans = ~a;
printf("%d\n", ans);

ans = a & b;
printf("%d\n", ans);

ans = a | b;
printf("%d\n", ans);

ans = a ^ b;
printf("%d\n", ans);

ans = a << 1;
printf("%d\n", ans);

ans = a >> 1;
printf("%d\n", ans);

return 0;
}

実行結果は以下の通りです。

-3
2
3
1
4
1

1番目のビット反転の結果が負の数になるのは、int型の符号を決める最上位ビット(MSB)0から1に変わるためです。5番目の左シフトでは、左側であふれたビットは削除され、右側には0が追加されます。6番目の右シフトでは、右側であふれたビットは削除され、左側には0(0または正の数の場合)または1(負の数の場合)が追加されます。

1-7.代入演算子

代入演算子は、変数に値を代入するための演算子です。単純に変数に値を代入することに加え、これまで解説した算術演算、ビット/シフト演算を行った上で代入することができます。表5は代入演算子の一覧です。

演算子 記述例 同じ意味の式 説明
= a = b 代入
+= a += b a = a + b 加算して代入
-= a -= b a = a – b 減算して代入
*= a *= b a = a * b 乗算して代入
/= a /= b a = a / b 除算して代入
%= a %= b a = a % b 剰余算して代入
&= a &= b a = a & b AND(ビット論理和)の結果を代入
|= a |= b a = a | b OR(ビット論理積)の結果を代入
^= a ^= b a = a ^ b XOR(ビット排他的論理和)の結果を代入
<<= a <<= b a = a << b 左シフトして代入
>>= a >>= b a = a >> b 右シフトして代入

表7. 代入演算子一覧

1-8.その他の演算子

その他の演算子でよく使うものとして、sizeof演算子とキャスト演算子について解説します。

sizeof演算子は、変数やデータ型のメモリサイズを調べるための演算子です。sizeof演算子を使用すると変数やデータ型のメモリサイズをバイト単位で得ることができます。sizeof演算子は配列の要素数を調べる場合などに使用されます。詳細な使い方は「C言語の配列とは」の記事で解説されていますので、使い方を知りたい方は参照してください。

キャスト演算子は、データ型の変換を行うための演算子です。C言語では演算の過程で暗黙的にデータ型の変換が行われることがあります。例えば代入演算子「=」を使う際に左右のデータ型が異なると、左辺のデータ型に変換されます。一方で明示的にデータ型を変換したい場合、キャスト演算子を使用することでデータ型の変換を行うことができます。キャスト演算子を使用する場合、データ型を変換したい変数の左側にデータ型を「()」で囲んで記述します。

例えばint型の変数「a」をdouble型に変換する場合は以下のように記述します。

(double)a

キャスト演算子を使用して演算を行う例を以下に示します。

#include 

int main(void){
    int a, b;
    double ans;

    a = 7;
    b = 2;

    ans = a / b;
    printf(“%f\n実行結果は以下の通りです。”, ans);

ans = a / (double)b;
printf(“%f\n”, ans);

    return 0;
}

実行結果は以下の通りです。

3.000000
3.500000

1-2.で解説した通り、int型のまま除算を行うと結果もint型となるため小数点以下が切り捨てられますが、キャスト演算子で一方の変数をdouble型に変換すると、除算の結果はdouble型となり、小数点以下を計算することができます。

2.演算子の優先順位

演算子には優先順位があり、式の中に複数の演算子が登場した場合は、優先順位に従って演算が行われます。四則演算で加減算よりも乗除算を先に行う、変数への代入は右辺の計算を行ってから代入する、といった順番で演算されるのは、この演算子の優先順位に従っているためです。

式の中に同じ優先順位の演算子が複数登場した場合、結合規則という考え方に従って演算が行われます。結合規則は優先順位ごとに決まっており、「左から右」「右から左」のどちらかです。

表8は演算子の優先順位および結合規則の一覧です。

優先順位 演算子 説明 結合規則
上が高くて下が低い ++,–(後置) 後置インクリメント/デクリメント 左から右
~,!,++,–(前置),
sizeof,(データ型)
ビット反転、論理否定、前置インクリメント/デクリメント、sizeof、キャスト 右から左
*,/,% 乗算、除算、剰余算 左から右
+,- 加算、減算
<<,>> シフト
>,>=,<,<= より大きい、以上、より小さい、以下
==,!= 等しい、等しくない
& ビット論理積
^ ビット排他的論理和
| ビット論理和
&& 論理積
|| 論理和
=,+=,-=,*=,/=,%=,
<<=,>>=,&=,^=,|=
代入 右から左

表8. 演算子の優先順位と結合規則

優先順位とは異なる順番で処理を行う場合は、「()」を使用することができます。1-5.で論理演算子「!」を使用して演算を行う例で「()」を使用しましたが、「()」で囲むことで「!」よりも優先度の低い「<」の演算を先に行うことができます。

3.さいごに

演算子の一覧と各演算子の使い方、優先順位について解説しました。演算子はプログラムでは必ずと言っていいほど使うものですが、各演算子の演算内容だけでなく優先順位を把握して使い、意図しない演算結果が出ないようにしましょう。必要に応じて「()」を使うと処理内容がわかりやすいプログラムになります。

PAGE TOP
タイトルとURLをコピーしました