C言語のプログラミングを始めると、すぐに「演算子」という言葉に出会います。
演算子は、数値の計算やデータの比較、論理的な操作など、プログラムを作成する上で欠かせない要素です。
このガイドでは、演算子の基本概念から具体的な使い方まで、初心者にもわかりやすく解説します。
演算子とは何か
C言語において、演算子はプログラム内でデータを操作するための基本的な要素です。
演算子を使うことで、数値の計算やデータの比較、論理的な操作などを行うことができます。
ここでは、演算子の基本概念とその種類について詳しく解説します。
演算子の基本概念
演算子は、1つまたは複数のオペランド(操作対象)に対して特定の操作を行う記号やキーワードです。
例えば、+
は加算演算子で、2つの数値を加算するために使用されます。
以下に、基本的な演算子の例を示します。
int a = 5;
int b = 3;
int sum = a + b; // 加算演算子を使用してaとbを加算
この例では、+ 演算子
が a
と b
の値を加算し、その結果を sum
に代入しています。
演算子の種類
C言語には多くの種類の演算子が存在し、それぞれ異なる操作を行います。
以下に、主な演算子の種類を紹介します。
- 算術演算子: 数値の加算、減算、乗算、除算、剰余を行います。
- 例:
+
,-
,*
,/
,%
- 代入演算子: 変数に値を代入します。
- 例:
=
,+=
,-=
,*=
,/=
,%=
- 比較演算子: 2つの値を比較し、真(true)または偽(false)を返します。
- 例:
==
,!=
,>
,<
,>=
,<=
- 論理演算子: 論理的な操作を行い、真または偽を返します。
- 例:
&&
,||
,!
- ビット演算子: ビット単位での操作を行います。
- 例:
&
,|
,^
,~
,<<
,>>
- その他の演算子: 特殊な操作を行う演算子も存在します。
- 例:
?:
(条件演算子),,
(コンマ演算子),sizeof
(サイズ演算子),&
(アドレス演算子),*
(間接参照演算子)
これらの演算子を適切に使い分けることで、C言語のプログラムを効率的に記述することができます。
次のセクションでは、各演算子の詳細と使用例について詳しく解説していきます。
算術演算子
算術演算子は、数値の計算を行うための基本的な演算子です。
C言語では、加算、減算、乗算、除算、剰余の5つの基本的な算術演算子が用意されています。
また、インクリメントとデクリメントという特殊な演算子も存在します。
基本的な算術演算子
加算(+)
加算演算子は、2つの数値を足し合わせるために使用されます。
#include <stdio.h>
int main() {
int a = 5;
int b = 3;
int sum = a + b; // 加算
printf("a + b = %d\n", sum); // 結果: 8
return 0;
}
減算(-)
減算演算子は、2つの数値の差を求めるために使用されます。
#include <stdio.h>
int main() {
int a = 5;
int b = 3;
int difference = a - b; // 減算
printf("a - b = %d\n", difference); // 結果: 2
return 0;
}
乗算(*)
乗算演算子は、2つの数値を掛け合わせるために使用されます。
#include <stdio.h>
int main() {
int a = 5;
int b = 3;
int product = a * b; // 乗算
printf("a * b = %d\n", product); // 結果: 15
return 0;
}
除算(/)
除算演算子は、2つの数値を割り算するために使用されます。
整数同士の除算では、結果も整数になります。
#include <stdio.h>
int main() {
int a = 5;
int b = 3;
int quotient = a / b; // 除算
printf("a / b = %d\n", quotient); // 結果: 1
return 0;
}
剰余(%)
剰余演算子は、2つの数値を割り算した余りを求めるために使用されます。
整数同士の演算でのみ使用されます。
#include <stdio.h>
int main() {
int a = 5;
int b = 3;
int remainder = a % b; // 剰余
printf("a %% b = %d\n", remainder); // 結果: 2
return 0;
}
インクリメント・デクリメント演算子
インクリメントとデクリメント演算子は、変数の値を1ずつ増減させるための演算子です。
インクリメント(++)
インクリメント演算子は、変数の値を1増やします。
前置インクリメントと後置インクリメントの2種類があります。
#include <stdio.h>
int main() {
int a = 5;
printf("a = %d\n", a); // 結果: 5
printf("++a = %d\n", ++a); // 前置インクリメント: 結果: 6
printf("a++ = %d\n", a++); // 後置インクリメント: 結果: 6
printf("a = %d\n", a); // 結果: 7
return 0;
}
デクリメント(–)
デクリメント演算子は、変数の値を1減らします。
前置デクリメントと後置デクリメントの2種類があります。
#include <stdio.h>
int main() {
int a = 5;
printf("a = %d\n", a); // 結果: 5
printf("--a = %d\n", --a); // 前置デクリメント: 結果: 4
printf("a-- = %d\n", a--); // 後置デクリメント: 結果: 4
printf("a = %d\n", a); // 結果: 3
return 0;
}
これらの基本的な算術演算子とインクリメント・デクリメント演算子を理解することで、C言語での数値計算がスムーズに行えるようになります。
次に、代入演算子について詳しく見ていきましょう。
代入演算子
代入演算子は、変数に値を設定するために使用されます。
C言語では、基本的な代入演算子と複合代入演算子があります。
これらの演算子を理解することで、コードの可読性と効率性を向上させることができます。
基本的な代入演算子
単純代入(=)
単純代入演算子 =
は、右辺の値を左辺の変数に代入します。
最も基本的な代入演算子であり、変数に初期値を設定したり、値を更新したりする際に使用されます。
#include <stdio.h>
int main() {
int a; // 変数aを宣言
a = 10; // 変数aに10を代入
printf("a = %d\n", a); // 結果を表示
return 0;
}
このコードを実行すると、以下のように表示されます。
a = 10
複合代入演算子
複合代入演算子は、代入と算術演算を同時に行うための演算子です。
これにより、コードを簡潔に記述することができます。
加算代入(+=)
加算代入演算子 +=
は、左辺の変数に右辺の値を加算し、その結果を左辺の変数に代入します。
#include <stdio.h>
int main() {
int a = 5;
a += 3; // a = a + 3 と同じ意味
printf("a = %d\n", a); // 結果を表示
return 0;
}
このコードを実行すると、以下のように表示されます。
a = 8
減算代入(-=)
減算代入演算子 -=
は、左辺の変数から右辺の値を減算し、その結果を左辺の変数に代入します。
#include <stdio.h>
int main() {
int a = 5;
a -= 2; // a = a - 2 と同じ意味
printf("a = %d\n", a); // 結果を表示
return 0;
}
このコードを実行すると、以下のように表示されます。
a = 3
乗算代入(*=)
乗算代入演算子 *=
は、左辺の変数に右辺の値を乗算し、その結果を左辺の変数に代入します。
#include <stdio.h>
int main() {
int a = 5;
a *= 2; // a = a * 2 と同じ意味
printf("a = %d\n", a); // 結果を表示
return 0;
}
このコードを実行すると、以下のように表示されます。
a = 10
除算代入(/=)
除算代入演算子 /=
は、左辺の変数を右辺の値で除算し、その結果を左辺の変数に代入します。
#include <stdio.h>
int main() {
int a = 10;
a /= 2; // a = a / 2 と同じ意味
printf("a = %d\n", a); // 結果を表示
return 0;
}
このコードを実行すると、以下のように表示されます。
a = 5
剰余代入(%=)
剰余代入演算子 %=
は、左辺の変数を右辺の値で割った余りを左辺の変数に代入します。
#include <stdio.h>
int main() {
int a = 10;
a %= 3; // a = a % 3 と同じ意味
printf("a = %d\n", a); // 結果を表示
return 0;
}
このコードを実行すると、以下のように表示されます。
a = 1
以上が、基本的な代入演算子と複合代入演算子です。
これらの演算子を理解し、適切に使用することで、コードの効率性と可読性を向上させることができます。
比較演算子
比較演算子は、2つの値を比較してその結果を真(1)または偽(0)で返す演算子です。
条件分岐やループなどでよく使用されます。
ここでは、基本的な比較演算子について解説します。
基本的な比較演算子
等しい(==)
等しい演算子は、2つの値が等しいかどうかを比較します。
等しい場合は真(1)、等しくない場合は偽(0)を返します。
#include <stdio.h>
int main() {
int a = 5;
int b = 5;
int c = 10;
printf("a == b: %d\n", a == b); // 1 (真)
printf("a == c: %d\n", a == c); // 0 (偽)
return 0;
}
等しくない(!=)
等しくない演算子は、2つの値が等しくないかどうかを比較します。
等しくない場合は真(1)、等しい場合は偽(0)を返します。
#include <stdio.h>
int main() {
int a = 5;
int b = 5;
int c = 10;
printf("a != b: %d\n", a != b); // 0 (偽)
printf("a != c: %d\n", a != c); // 1 (真)
return 0;
}
より大きい(>)
より大きい演算子は、左側の値が右側の値より大きいかどうかを比較します。
大きい場合は真(1)、そうでない場合は偽(0)を返します。
#include <stdio.h>
int main() {
int a = 10;
int b = 5;
printf("a > b: %d\n", a > b); // 1 (真)
printf("b > a: %d\n", b > a); // 0 (偽)
return 0;
}
より小さい(<)
より小さい演算子は、左側の値が右側の値より小さいかどうかを比較します。
小さい場合は真(1)、そうでない場合は偽(0)を返します。
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
printf("a < b: %d\n", a < b); // 1 (真)
printf("b < a: %d\n", b < a); // 0 (偽)
return 0;
}
以上(>=)
以上演算子は、左側の値が右側の値以上かどうかを比較します。
以上の場合は真(1)、そうでない場合は偽(0)を返します。
#include <stdio.h>
int main() {
int a = 10;
int b = 5;
int c = 10;
printf("a >= b: %d\n", a >= b); // 1 (真)
printf("a >= c: %d\n", a >= c); // 1 (真)
printf("b >= a: %d\n", b >= a); // 0 (偽)
return 0;
}
以下(<=)
以下演算子は、左側の値が右側の値以下かどうかを比較します。
以下の場合は真(1)、そうでない場合は偽(0)を返します。
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
int c = 5;
printf("a <= b: %d\n", a <= b); // 1 (真)
printf("a <= c: %d\n", a <= c); // 1 (真)
printf("b <= a: %d\n", b <= a); // 0 (偽)
return 0;
}
これらの比較演算子を使うことで、条件分岐やループの制御が可能になります。
次に、論理演算子について解説します。
論理演算子
論理演算子は、主に条件式の評価に使用されます。
これらの演算子は、真(true)または偽(false)の値を操作し、複数の条件を組み合わせて評価する際に非常に便利です。
C言語では、以下の3つの基本的な論理演算子が提供されています。
基本的な論理演算子
論理積(&&)
論理積演算子(&&)は、2つの条件が両方とも真である場合にのみ真を返します。
どちらか一方でも偽であれば、結果は偽となります。
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
int c = 5;
if (a == c && b > a) {
printf("条件は真です。\n");
} else {
printf("条件は偽です。\n");
}
return 0;
}
このコードでは、a == c
と b > a
の両方が真であるため、出力は「条件は真です。」となります。
論理和(||)
論理和演算子(||)は、2つの条件のうち少なくとも1つが真であれば真を返します。
両方の条件が偽である場合にのみ、結果は偽となります。
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
int c = 15;
if (a == c || b > a) {
printf("条件は真です。\n");
} else {
printf("条件は偽です。\n");
}
return 0;
}
このコードでは、a == c
は偽ですが、b > a
が真であるため、出力は「条件は真です。」となります。
否定(!)
否定演算子(!)は、条件の真偽を反転させます。
条件が真であれば偽を返し、条件が偽であれば真を返します。
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
if (!(a == b)) {
printf("条件は真です。\n");
} else {
printf("条件は偽です。\n");
}
return 0;
}
このコードでは、a == b
は偽であるため、!(a == b)
は真となり、出力は「条件は真です。」となります。
これらの論理演算子を組み合わせることで、複雑な条件式を簡潔に表現することができます。
条件分岐やループの制御において非常に重要な役割を果たします。
ビット演算子
ビット演算子は、整数のビット単位での操作を行うための演算子です。
これらの演算子は、特に低レベルのプログラミングやハードウェア制御において非常に重要です。
ビット演算子には、AND、OR、XOR、NOT、シフト演算子などがあります。
基本的なビット演算子
AND(&)
AND演算子
は、対応するビットが両方とも1である場合に1を返します。
それ以外の場合は0を返します。
#include <stdio.h>
int main() {
int a = 5; // 0101
int b = 3; // 0011
int result = a & b; // 0001
printf("a & b = %d\n", result); // 出力: a & b = 1
return 0;
}
OR(|)
OR演算子
は、対応するビットのどちらかが1である場合に1を返します。
両方が0の場合のみ0を返します。
#include <stdio.h>
int main() {
int a = 5; // 0101
int b = 3; // 0011
int result = a | b; // 0111
printf("a | b = %d\n", result); // 出力: a | b = 7
return 0;
}
XOR(^)
XOR演算子
は、対応するビットが異なる場合に1を返します。
同じ場合は0を返します。
#include <stdio.h>
int main() {
int a = 5; // 0101
int b = 3; // 0011
int result = a ^ b; // 0110
printf("a ^ b = %d\n", result); // 出力: a ^ b = 6
return 0;
}
NOT(~)
NOT演算子
は、ビットを反転させます。
つまり、1を0に、0を1に変えます。
#include <stdio.h>
int main() {
int a = 5; // 0101
int result = ~a; // 1010 (2の補数表現では-6)
printf("~a = %d\n", result); // 出力: ~a = -6
return 0;
}
シフト演算子
シフト演算子は、ビットを左または右にシフトするために使用されます。
シフト演算子には、左シフト(<<)と右シフト(>>)があります。
左シフト(<<)
左シフト演算子は、ビットを指定された数だけ左にシフトします。
シフトされたビットの右側には0が入ります。
#include <stdio.h>
int main() {
int a = 5; // 0101
int result = a << 1; // 1010
printf("a << 1 = %d\n", result); // 出力: a << 1 = 10
return 0;
}
右シフト(>>)
右シフト演算子は、ビットを指定された数だけ右にシフトします。
シフトされたビットの左側には符号ビットが入ります(符号付き整数の場合)。
#include <stdio.h>
int main() {
int a = 5; // 0101
int result = a >> 1; // 0010
printf("a >> 1 = %d\n", result); // 出力: a >> 1 = 2
return 0;
}
ビット演算子は、効率的なビット操作を行うための強力なツールです。
これらの演算子を理解し、適切に使用することで、より効率的なプログラムを作成することができます。
その他の演算子
C言語には、算術演算子や論理演算子以外にもさまざまな演算子が存在します。
ここでは、条件演算子、コンマ演算子、サイズ演算子、ポインタ演算子について詳しく解説します。
条件演算子(三項演算子)
条件演算子(?:)
条件演算子は、三項演算子とも呼ばれ、条件に基づいて異なる値を返すために使用されます。
構文は以下の通りです。
条件式 ? 式1 : 式2
条件式が真(true)の場合は式1が評価され、偽(false)の場合は式2が評価されます。
以下に具体例を示します。
#include <stdio.h>
int main() {
int a = 10, b = 20;
int max;
// 条件演算子を使用して最大値を求める
max = (a > b) ? a : b;
printf("最大値は %d です。\n", max);
return 0;
}
このプログラムでは、変数a
とb
のうち大きい方の値をmax
に代入しています。
実行結果は以下の通りです。
最大値は 20 です。
コンマ演算子
コンマ演算子(,)
コンマ演算子は、複数の式を一つの文で評価するために使用されます。
コンマ演算子を使用すると、左から右へ順に式が評価され、最後の式の値が返されます。
以下に具体例を示します。
#include <stdio.h>
int main() {
int a, b, c;
// コンマ演算子を使用して複数の式を評価
a = (b = 3, c = 4, b + c);
printf("a = %d\n", a);
return 0;
}
このプログラムでは、b
に3を、c
に4を代入し、その後b + c
の結果をa
に代入しています。
実行結果は以下の通りです。
a = 7
サイズ演算子
サイズ演算子(sizeof)
サイズ演算子sizeof
は、変数やデータ型のメモリサイズをバイト単位で返します。
以下に具体例を示します。
#include <stdio.h>
int main() {
int a;
double b;
printf("int型のサイズ: %zu バイト\n", sizeof(a));
printf("double型のサイズ: %zu バイト\n", sizeof(b));
return 0;
}
このプログラムでは、int型
とdouble型
の変数のサイズを表示しています。
実行結果は以下の通りです。
int型のサイズ: 4 バイト
double型のサイズ: 8 バイト
ポインタ演算子
アドレス演算子(&)
アドレス演算子&
は、変数のメモリアドレスを取得するために使用されます。
以下に具体例を示します。
#include <stdio.h>
int main() {
int a = 10;
int *p;
// 変数aのアドレスをポインタpに代入
p = &a;
printf("aのアドレス: %p\n", (void *)p);
return 0;
}
このプログラムでは、変数a
のアドレスをポインタ変数p
に代入し、そのアドレスを表示しています。
実行結果は以下の通りです。
aのアドレス: 0x7ffee3b7a6ac
間接参照演算子(*)
間接参照演算子*
は、ポインタが指すメモリアドレスの値を取得するために使用されます。
以下に具体例を示します。
#include <stdio.h>
int main() {
int a = 10;
int *p;
// 変数aのアドレスをポインタpに代入
p = &a;
// ポインタpが指す値を表示
printf("pが指す値: %d\n", *p);
return 0;
}
このプログラムでは、ポインタp
が指す値(つまり変数a
の値)を表示しています。
実行結果は以下の通りです。
pが指す値: 10
以上が、C言語におけるその他の演算子です。
これらの演算子を理解し、適切に使用することで、より効率的で読みやすいコードを書くことができます。
演算子の優先順位と結合規則
C言語では、複数の演算子が一つの式に含まれる場合、どの演算子が先に評価されるかを決定するために「演算子の優先順位」と「結合規則」が重要です。
これらを理解することで、意図した通りにプログラムが動作するようにコードを書くことができます。
演算子の優先順位
演算子の優先順位は、どの演算子が他の演算子よりも先に評価されるかを決定します。
以下に、一般的な演算子の優先順位を高い順に示します。
優先順位 | 演算子 | 説明 |
---|---|---|
1 | () | 括弧 |
2 | ++ , -- | 前置インクリメント、前置デクリメント |
3 | * , & | ポインタ演算子 |
4 | * , / , % | 乗算、除算、剰余 |
5 | + , - | 加算、減算 |
6 | << , >> | シフト演算子 |
7 | < , <= , > , >= | 比較演算子 |
8 | == , != | 等価演算子 |
9 | & | ビットAND |
10 | ^ | ビットXOR |
11 | | | ビットOR |
12 | && | 論理AND |
13 | || | 論理OR |
14 | ?: | 条件演算子 |
15 | = , += , -= , *= , /= , %= | 代入演算子 |
16 | , | コンマ演算子 |
例えば、以下の式を考えてみましょう。
int result = 3 + 5 * 2;
この場合、*
(乗算)の優先順位が+
(加算)よりも高いため、まず5 * 2
が評価され、その後に3 + 10
が評価されます。
結果として、result
には13
が代入されます。
結合規則
結合規則は、同じ優先順位の演算子が複数存在する場合に、どの順序で評価されるかを決定します。
結合規則には「左結合」と「右結合」の2種類があります。
- 左結合: 左から右に評価される
- 右結合: 右から左に評価される
例えば、加算(+)
と減算(-)
は左結合です。
int result = 10 - 3 + 2;
この場合、10 - 3
が先に評価され、その後に7 + 2
が評価されます。
結果として、result
には9
が代入されます。
一方、代入演算子(=)
は右結合です。
int a, b, c;
a = b = c = 5;
この場合、まずc = 5
が評価され、その後にb = 5
、最後にa = 5
が評価されます。
結果として、a
, b
, c
のすべてに5
が代入されます。
演算子の優先順位と結合規則をしっかりと理解し、正確なコードを書くことを心がけましょう。
演算子の使用例
ここでは、C言語の演算子を実際にどのように使用するかについて具体的な例を示します。
基本的な使用例から応用的な使用例まで、段階的に解説していきます。
基本的な使用例
まずは、基本的な演算子の使用例を見ていきましょう。
以下のコードは、算術演算子、代入演算子、比較演算子、論理演算子を使った簡単なプログラムです。
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
int result;
// 算術演算子の使用例
result = a + b; // 加算
printf("a + b = %d\n", result);
result = b - a; // 減算
printf("b - a = %d\n", result);
result = a * b; // 乗算
printf("a * b = %d\n", result);
result = b / a; // 除算
printf("b / a = %d\n", result);
result = b % a; // 剰余
printf("b %% a = %d\n", result);
// 比較演算子の使用例
if (a == b) {
printf("a は b と等しい\n");
} else {
printf("a は b と等しくない\n");
}
if (a < b) {
printf("a は b より小さい\n");
}
// 論理演算子の使用例
if (a < b && b > 15) {
printf("a は b より小さく、b は 15 より大きい\n");
}
return 0;
}
このプログラムを実行すると、以下のような出力が得られます。
a + b = 30
b - a = 10
a * b = 200
b / a = 2
b % a = 0
a は b と等しくない
a は b より小さい
a は b より小さく、b は 15 より大きい
応用的な使用例
次に、もう少し複雑な演算子の使用例を見てみましょう。
ここでは、ビット演算子や条件演算子、シフト演算子を使った例を紹介します。
#include <stdio.h>
int main() {
int x = 5; // 0101 in binary
int y = 3; // 0011 in binary
int result;
// ビット演算子の使用例
result = x & y; // AND
printf("x & y = %d\n", result); // 0001 in binary, which is 1
result = x | y; // OR
printf("x | y = %d\n", result); // 0111 in binary, which is 7
result = x ^ y; // XOR
printf("x ^ y = %d\n", result); // 0110 in binary, which is 6
result = ~x; // NOT
printf("~x = %d\n", result); // 1111...1010 in binary, which is -6 (2's complement)
// シフト演算子の使用例
result = x << 1; // 左シフト
printf("x << 1 = %d\n", result); // 1010 in binary, which is 10
result = x >> 1; // 右シフト
printf("x >> 1 = %d\n", result); // 0010 in binary, which is 2
// 条件演算子の使用例
int max = (x > y) ? x : y;
printf("max = %d\n", max); // x が y より大きければ x、そうでなければ y
return 0;
}
このプログラムを実行すると、以下のような出力が得られます。
x & y = 1
x | y = 7
x ^ y = 6
~x = -6
x << 1 = 10
x >> 1 = 2
max = 5
これらの例を通じて、C言語の演算子がどのように使われるかを理解することができたでしょう。
基本的な使用例から応用的な使用例まで、さまざまな場面で演算子を活用することができます。