Menu

C++の演算子: 算術・比較・論理ほか

C++の演算子(算術・比較・論理・代入・ビット演算)を学びましょう。整数除算、優先順位、短絡評価にまつわる落とし穴も解説します。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

演算子の役割

演算子とは、オペランドと呼ばれる1つ以上の値に対して操作を行う記号です。あなたはすでに1つ使っています。値を変数に結びつける=です。C++には、数学・比較・論理・ビット操作のための豊富な演算子がそろっており、初心者がつまずく鋭い落とし穴もいくつかあります。

前のページでは、constが値を固定する様子を見ました。演算子は、定数であってもなくても、保存する値を計算するための手段です。毎日使うことになる各グループを順に見ていきましょう。

算術演算子

5つの算術演算子は +-*/、そして %(剰余、除算の余り)です。

大きな落とし穴はその商にあります。17 / 53.4 ではなく 3 を表示します。両方のオペランドが整数のとき、/は整数除算を行い、小数部分を捨てます。ゼロ方向に切り捨てるのであって、丸めるわけではありません。本当の分数が欲しいなら、少なくとも一方のオペランドを浮動小数点にする必要があります。

%演算子は整数にしか使えません。double%を使うとコンパイルエラーになります。浮動小数点の余りには<cmath>std::fmodを使いましょう。

代入と複合代入演算子

単独の=代入するものであって、比較はしません。C++には、操作と代入を組み合わせて変数名を繰り返さずに済む複合形があります。

古典的でつらいミスは、条件の中で==のつもりで=と書いてしまうことです。if (x = 0) は比較するのではなく、xに0を代入してからその結果(偽になります)を判定します。最近のコンパイラは警告を有効にするとこれを知らせてくれます。-Wallを有効にしたまま、その警告を真剣に受け止めましょう。

比較演算子

比較演算子はイエス/ノーの問いを立て、booltrueまたはfalse)を返します。

既定ではcoutbool1または0として表示します。boolalphaを一度ストリームに流すと、そのストリームの残りではtrue/falseという単語に切り替わります。

微妙な罠として、1 < x < 10 のように比較を連鎖させないでください。これは (1 < x) < 10 と解釈されます。最初の比較がbool(0または1)を生み、それが10と比較されるため、全体はほぼ常にtrueになります。代わりに 1 < x && x < 10 と書きましょう。

論理演算子と短絡評価

&&(かつ)、||(または)、!(否定)はブール式を組み合わせます。最初の2つは短絡評価を行い、結果が判明した時点で評価を止めます。

check("A")check("B")も実行されません。これが短絡評価です。これは単なる最適化ではなく、道具でもあります。if (ptr != nullptr && ptr->ready) と安全に書けるのは、ptr->readyの部分がptrが非nullのときにしか到達されず、ダングリングポインタの参照外しを避けられるからです。

インクリメントとデクリメント

++は1を足し、--は1を引きます。それぞれに前置形と後置形があり、結果を使うときにその違いが効いてきます。

副作用だけが目的のとき(たとえばforループ)は++iを使いましょう。素のintでは同じですが、イテレータのような重い型では、後置インクリメントはまず古い値をコピーしなければならず、それは無駄な処理になります。

もう1つ注意があります。i = i++ + 1;arr[i] = i++; のように、1つの式の中で同じ変数を2回変更しないでください。これらの更新の順序は規定されておらず、結果は未定義動作です。各変数の変更は1つの文につき1回にとどめましょう。

ビット演算子と優先順位

低レベルの作業にはビット演算子があります。&(かつ)、|(または)、^(xor)、~(否定)、そしてシフトの<<>>です。

注意: <<>>coutのストリーム演算子でもあります。coutの行の中では、ビットシフトの周りに通常は括弧が必要です。そうしないと、コンパイラはそれをストリームへの挿入として読んでしまいます。

最後に、優先順位は、演算子を混ぜたときにどれが先に結びつくかを決めます。数学と同じく*/+-より強く結びつくので、2 + 3 * 414です。比較は算術より弱く、論理の&&/||はさらに弱く結びつきます。迷ったら表を丸暗記せず、括弧を付けましょう。(a + b) * cのほうが、読み手がルールを覚えていることに頼るより明確です。

次は: 型キャスト

上で(double)a / bが整数を浮動小数点除算へと強制したのを見ました。これがキャストです。値を意図的にある型から別の型へ変換することです。次のページでは、暗黙の昇格からstatic_castまで、C++の変換ツールと、それぞれがいつ安全かを扱います。

よくある質問

C++の演算子にはどんなものがありますか?

C++では演算子を、算術(+ - * / %)、比較(== != < > <= >=)、論理(&& || !)、代入(= += -= ...)、インクリメント/デクリメント(++ --)、ビット(& | ^ ~ << >>)に分類します。ほかに三項演算子?:や、sizeofのようなものもいくつかあります。

C++で 5 / 2 が 2 になるのはなぜですか?

両方のオペランドがintなので、/は整数除算を行い、小数部分は丸められるのではなく切り捨てられるからです。2.5を得るには、少なくとも一方のオペランドを浮動小数点の値にします: 5.0 / 2 または 5 / 2.0

C++で ++i と i++ の違いは何ですか?

どちらもiに1を加えます。++i(前置インクリメント)は先に加算して新しい値を返します。i++(後置インクリメント)は古い値を返してから加算します。副作用だけが目的なら++iを使いましょう。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める