はじめに

この実験では、C++ の演算子の使い方を学びます。算術演算子、比較演算子、論理演算子、ビット演算子の使い方を学びます。

コンテンツプレビュー

基本的な数値と論理データに対して、演算子を使って操作します。他の言語と同様に、C++ は演算子に対して十分なサポートを提供しています。これから学んでいきましょう。

  • 算術演算
  • 混合型演算
  • 複合代入演算子
  • 型キャスト
  • 比較演算子と論理演算子

算術演算

C++ は数値に対して次の算術演算子をサポートしています。

演算子 説明 使い方
* 乗算 expr1 * expr2 2 * 3 → 6; 3.3 * 1.0 → 3.3
/ 除算 expr1 / expr2 1 / 2 → 0; 1.0 / 2.0 → 0.5
% 余り (剰余) expr1 % expr2 5 % 2 → 1; -5 % 2 → -1
+ 加算 expr1 + expr2 1 + 2 → 3; 1.1 + 2.2 → 3.3
- 減算 expr1 - expr2 1 - 2 → -1; 1.1 - 2.2 → -1.1

上記の演算子はすべて 2 項演算子で、2 つのオペランドを取ります。乗算、除算、余りは加算と減算よりも優先順位が高いです。

int/intint を生成し、結果が切り捨てられることに注意することが重要です。1/2 → 0 (0.5 ではありません)。

混合型演算

算術演算のオペランドの両方が同じ型に属する場合、演算はその型で行われ、結果もその型に属します。ただし、2 つのオペランドが異なる型に属する場合、コンパイラは小さい方の型の値を大きい方の型に昇格させます(暗黙的な型キャストと呼ばれます)。その後、演算は大きい方の型で行われます。

演算
int 2 + 3 int 2 + int 3 → int 5
double 2.2 + 3.3 double 2.2 + double 3.3 → double 5.5
混合 2 + 3.3 int 2 + double 3.3 → double 2.0 + double 3.3 → double 5.3
int 1 / 2 int 1 / int 2 → int 0
double 1.0 / 2.0 double 1.0 / double 2.0 → double 0.5
混合 1 / 2.0 int 1 / double 2.0 → double 1.0 + double 2.0 → double 0.5

/* 混合型算術演算のテスト */
#include <iostream>
#include <iomanip>   // 浮動小数点数の書式設定に必要
using namespace std;

int main() {
   int i1 = 2, i2 = 4;
   double d1 = 2.5, d2 = 5.0;

   // 少数第 1 位で固定形式の浮動小数点数
   cout<<fixed<<setprecision(1);

   cout << i1 << " + " << i2 << " = " << i1+i2 << endl;  // 6
   cout << d1 << " + " << d2 << " = " << d1+d2 << endl;  // 7.5
   cout << i1 << " + " << d2 << " = " << i1+d2 << endl;  // 7.0  <==

   cout << i1 << " - " << i2 << " = " << i1-i2 << endl;  // -2
   cout << d1 << " - " << d2 << " = " << d1-d2 << endl;  // -2.5
   cout << i1 << " - " << d2 << " = " << i1-d2 << endl;  // -3.0 <==

   cout << i1 << " * " << i2 << " = " << i1*i2 << endl;  // 8
   cout << d1 << " * " << d2 << " = " << d1*d2 << endl;  // 12.5
   cout << i1 << " * " << d2 << " = " << i1*d2 << endl;  // 10.0 <==

   cout << i1 << " / " << i2 << " = " << i1/i2 << endl;  // 0    <==
   cout << d1 << " / " << d2 << " = " << d1/d2 << endl;  // 0.5
   cout << i1 << " / " << d2 << " = " << i1/d2 << endl;  // 0.4  <==
   return 0;
}

出力:

2 + 4 = 6
2.5 + 5.0 = 7.5
2 + 5.0 = 7.0
2 - 4 = -2
2.5 - 5.0 = -2.5
2 - 5.0 = -3.0
2 * 4 = 8
2.5 * 5.0 = 12.5
2 * 5.0 = 10.0
2 / 4 = 0
2.5 / 5.0 = 0.5

画像の説明

オーバーフロー / アンダーフロー

// int の範囲は [-2147483648, 2147483647]
   int i1 = 2147483647;      // int の最大値
   cout << i1 + 1 << endl;   // -2147483648 (オーバーフロー)
   cout << i1 * i1 << endl;  // 1

   int i2 = -2147483648;     // int の最小値
   cout << i2 - 1 << endl;   // 2147483647 (アンダーフロー)
   cout << i2 * i2 << endl;  // 0

算術演算では、結果の値がその範囲を超える場合、その値は循環します。C++ ランタイムはエラー/警告メッセージを発行せず、代わりに誤った結果を生成します。オーバーフロー/アンダーフローのチェックはプログラマーの責任であることに注意することが重要です。

複合代入演算子

C++ はまた、次のように列挙されるいわゆる 複合代入演算子 も提供しています。

演算子 使い方 説明
= var = expr 左辺の値を右辺の変数に代入する x = 5;
+= var += expr var = var + expr と同じ x += 5; は x = x + 5 と同じ
-= var -= expr var = var - expr と同じ x -= 5; は x = x - 5 と同じ
*= var *= expr var = var * expr と同じ x *= 5; は x = x * 5 と同じ
/= var /= expr var = var / expr と同じ x /= 5; は x = x / 5 と同じ
%= var %= expr var = var % expr と同じ x %= 5; は x = x % 5 と同じ
++ ++x 前置インクリメント y=++x; は x=x+1;y=x と同じ
++ x++ 後置インクリメント y=x++; は oldX=x; x=x+1; y=oldX と同じ
-- --x 前置デクリメント y=--x; は x=x-1;y=x と同じ
-- x-- 後置デクリメント y=x--; は oldX=x; x=x-1; y=oldX と同じ
x = 5;
cout << x++ << endl;  // x を保存 (5); x をインクリメント (=6); 古い x (5) を出力する。
x = 5;
cout << ++x << endl;  // x をインクリメント (=6); x を出力する (6)。

暗黙的な型変換と明示的な型キャスト

基本型(組み込み型)の値を別の基本型の変数に代入する場合、C++ は 2 つの型が互換性がある場合、自動的に値を受け取る型に変換します。例えば、

  • int 型の値を double 型の変数に代入する場合、コンパイラは自動的に int 型の値を double 型にキャストします(たとえば、1 から 1.0 に)し、それを double 型の変数に代入します。
  • double 型の値を int 型の変数に代入する場合、コンパイラは自動的に double 型の値を int 型の値にキャストします(たとえば、1.2 から 1 に)し、それを int 型の変数に代入します。小数部分は切り捨てられて失われます。一部のコンパイラは「精度の損失があり得る」という警告/エラーを発行します。他のコンパイラはそうしません。
 int i;
 double d;

 i = 3;
 d = i;    // int 型の値を double 型に代入
 cout << "d = " << d << endl;  // 3.0

 d = 5.5;
 i = d;    // double 型の値を int 型に代入
 cout << "i = " << i << endl;  // 5 (切り捨てられ、警告なし!)

(新しい型) オペランド または 新しい型 (オペランド) の形式のいわゆる単項の 型キャスト演算子 を使って明示的に型キャストを行うことができます。型キャスト演算子は特定の型の 1 つのオペランドを取り、新しい型の等価な値を返します。これは、加算演算子が 2 つのオペランドを使うのと同じように、結果の値を生成する演算であることに注意してください。たとえば、

cout << (double)5 << endl;  // int 5 → double 5.0
cout << (int)5.5 << endl;   // double 5.5 → int 5

double aDouble = 5.6;
int anInt = (int)aDouble; // 5 を返して anInt に代入。aDouble は変化しません!

// C++ は関数スタイルの型キャストもサポートしています。
cout << double(5) << endl;     // 5.0
cout << int(5.5) << endl;      // 5
cout << int(aDouble) << endl;  // 5

比較演算子と論理演算子

多くの場合、実行するアクションを決定する前に 2 つの値を比較する必要があります。C++ は 6 つの 比較演算子(または 関係演算子)を提供しています。

演算子 説明 使い方 例 (x=5, y=8)
== 等しい expr1 == expr2 (x == y) → false
!= 等しくない expr1!= expr2 (x!= y) → true
> 大きい expr1 > expr2 (x > y) → false
>= 大きいか等しい expr1 >= expr2 (x >= 5) → true
< 小さい expr1 < expr2 (y < 8) → false
<= 小さいか等しい expr1 <= expr2 (y <= 8) → true
&& 論理積 expr1 && expr2
|| 論理和 expr1 || expr2
! 論理否定 !expr
^ 排他的論理和 expr1 ^ expr2

真理値表は次の通りです。

論理積 (&&) true false
true true false
false false false
論理和 (||) true false
true true true
false true false
否定 (!) true false
false true
排他的論理和 (^) true false
true false true
false true false
// x が 0 以上 100 以下(両端含む)の場合に true を返す
(x >= 0) && (x <= 100)
// 0 <= x <= 100 を使うのは誤り

// x が 0 以上 100 以下(両端含む)の範囲外の場合に true を返す
(x < 0) \|\| (x > 100)   // または
!((x >= 0) && (x <= 100))

// year がうるう年の場合に true を返す
// 年が 4 で割り切れ、かつ 100 で割り切れない、または 400 で割り切れる場合、その年はうるう年である。
((year % 4 == 0) && (year % 100!= 0)) \|\| (year % 400 == 0)

まとめ

この部分は比較的簡単です。前のセクションと関連付けて理解してください。丸暗記する必要はありません。論理を理解しておきましょう。