CおよびC++の演算子

これは、 CおよびC++プログラミング言語演算子 のリストです

記載されている演算子はすべてC++で記述されており、特に記載がない場合はCでも記述されます。一部の表には「C」列があり、演算子がCでも記述されているかどうかを示しています。Cは演算子のオーバーロードをサポートしていないことに注意してください。

オーバーロードされていない場合、演算子&&||、および,(コンマ演算子) では、最初のオペランドの評価後に シーケンス ポイントが存在します。

C および C++ で使用できる演算子のほとんどは、同じ優先順位、結合性、およびセマンティクスで、 C#DJavaPerlPHPなどの他のC ファミリ言語でも使用できます。

記号列で指定される多くの演算子は、通常、各記号の名前を組み合わせた名前で呼ばれます。例えば、+=と は、-=より冗長な「加算による代入」や「減算による代入」ではなく、「プラス・イコール」や「マイナス・イコール」と呼ばれることがよくあります。

オペレーター

a以下の表では、やなどの小文字はb、リテラル値、オブジェクト名/変数名、または左辺値(それぞれ適切なもの)を表します。R、 、STデータ型、 はKクラスまたは列挙型を表します。一部の演算子には、二重音字や三重音字、あるいは演算子の同義語を用いた代替表記があります。

算術

C と C++ には同じ算術演算子があり、すべて C++ でオーバーロードできます。

手術 構文 C++プロトタイプ
Kクラス 授業外
追加 a + b R K::operator +(S b); R operator +(K a, S b);
減算 a - b R K::operator -(S b); R operator -(K a, S b);
単項加算;整数昇格 +a R K::operator +(); R operator +(K a);
単項マイナス;加法逆数 -a R K::operator -(); R operator -(K a);
乗算 a * b R K::operator *(S b); R operator *(K a, S b);
分割 a / b R K::operator /(S b); R operator /(K a, S b);
モジュロ[a] a % b R K::operator %(S b); R operator %(K a, S b);
プレフィックス増分 ++a R& K::operator ++(); R& operator ++(K& a);
接尾辞インクリメント a++ R K::operator ++(int);[b] R operator ++(K& a, int);[b]
プレフィックスデクリメント --a R& K::operator --(); R& operator --(K& a);
後置デクリメント a-- R K::operator --(int);[b] R operator --(K& a, int);[b]

リレーショナル

C++では、すべての関係(比較)演算子をオーバーロードできます。C ++20以降では、が定義されている場合は不等号演算子が自動的に生成されoperator==、が定義されている場合は4つの関係演算子すべてが自動的に生成されますoperator<=>[1]

手術 構文 C言語 C++プロトタイプ
Kクラス 授業外
等しい a == b はい bool K::operator ==(S const& b) const; bool operator ==(K const& a, S const& b);
等しくない a != b はい bool K::operator !=(S const& b) const; bool operator !=(K const& a, S const& b);
より大きい a > b はい bool K::operator >(S const& b) const; bool operator >(K const& a, S const& b);
未満 a < b はい bool K::operator <(S const& b) const; bool operator <(K const& a, S const& b);
より大きいか等しい a >= b はい bool K::operator >=(S const& b) const; bool operator >=(K const& a, S const& b);
以下 a <= b はい bool K::operator <=(S const& b) const; bool operator <=(K const& a, S const& b);
三者比較[c] [d] a <=> b いいえ auto K::operator <=>(const S &b); auto operator <=>(const K &a, const S &b);

論理的

C と C++ には同じ論理演算子があり、すべて C++ でオーバーロードできます。

論理ANDORのオーバーロードは推奨されないことに注意してください。オーバーロードされた演算子は、短絡評価の通常の意味を提供するのではなく、常に両方のオペランドを評価するためです[2]

手術 構文 C++プロトタイプ
Kクラス 授業外
ない !a bool K::operator !(); bool operator !(K a);
そして a && b bool K::operator &&(S b); bool operator &&(K a, S b);
または a || b bool K::operator ||(S b); bool operator ||(K a, S b);

ビット単位

C と C++ には同じビット演算子があり、すべて C++ でオーバーロードできます。

手術 構文 C++プロトタイプ
Kクラス 授業外
ない ~a
R K::operator ~(); R operator ~(K a);
そして a & b R K::operator &(S b); R operator &(K a, S b);
または a | b R K::operator |(S b); R operator |(K a, S b);
排他的論理和 a ^ b R K::operator ^(S b); R operator ^(K a, S b);
シフト[e] a << b R K::operator <<(S b); R operator <<(K a, S b);
右シフト[e] [f] a >> b R K::operator >>(S b); R operator >>(K a, S b);

割り当て

C と C++ には同じ代入演算子があり、すべて C++ でオーバーロードできます。

組み合わせ演算子の場合、a ⊚= b( は演算を表します)は と同等ですa = a ⊚ bが、 はa1 回だけ評価されます。

手術 構文 C++プロトタイプ
Kクラス 授業外
割り当て a = b R& K::operator =(S b); 該当なし
加算組み合わせ a += b R& K::operator +=(S b); R& operator +=(K& a, S b);
引き算の組み合わせ a -= b R& K::operator -=(S b); R& operator -=(K& a, S b);
掛け算の組み合わせ a *= b R& K::operator *=(S b); R& operator *=(K& a, S b);
部門の組み合わせ a /= b R& K::operator /=(S b); R& operator /=(K& a, S b);
モジュロ組み合わせ a %= b R& K::operator %=(S b); R& operator %=(K& a, S b);
ビットANDの組み合わせ a &= b R& K::operator &=(S b); R& operator &=(K& a, S b);
ビットORの組み合わせ a |= b R& K::operator |=(S b); R& operator |=(K& a, S b);
ビット単位のXOR組み合わせ a ^= b R& K::operator ^=(S b); R& operator ^=(K& a, S b);
ビット単位の左シフトの組み合わせ a <<= b R& K::operator <<=(S b); R& operator <<=(K& a, S b);
ビット単位の右シフトの組み合わせ[g] a >>= b R& K::operator >>=(S b); R& operator >>=(K& a, S b);

メンバーとポインタ

手術 構文 過負荷になる可能性がある C言語 C++プロトタイプ
Kクラス 授業外
添字 a[b]a<:b:>[4] はい はい R& K::operator [](S b);
R& K::operator [](S b, ...);[h]
該当なし
間接参照( a
が指すオブジェクト
*a はい はい R& K::operator *(); R& operator *(K a);
Address-of ( a
のアドレス)
&a はい[i] はい R* K::operator &(); R* operator &(K a);
構造体の逆参照
aが指すオブジェクトのメンバーb
a->b はい はい R* K::operator ->();[j]
該当なし
構造体参照
オブジェクトaのメンバーb
a.b いいえ はい 該当なし
a [k]が指すオブジェクトのメンバーへのポインタ bによって選択されたメンバー a->*b はい いいえ R& K::operator ->*(S b); R& operator ->*(K a, S b);
オブジェクトaのメンバーはメンバーbへのポインタ によって選択されます a.*b いいえ いいえ 該当なし

他の

手術 構文 過負荷になる可能性がある C言語 C++プロトタイプ
Kクラス 授業外
関数呼び出し a(a1, a2) はい はい R K::operator ()(S a, T b, ...); 該当なし
コンマ a, b はい はい R K::operator ,(S b); R operator ,(K a, S b);
三項条件文 a ? b : c いいえ はい 該当なし
スコープ解決 a::b[l] いいえ いいえ 該当なし
ユーザー定義リテラル[m] [n] "a"_b はい いいえ 該当なし R operator "" _b(T a)
サイズ sizeof a[お]
sizeof (R)
いいえ はい 該当なし
パラメータパックのサイズ[n] sizeof...(Args) いいえ いいえ 該当なし
アラインオフ[n] alignof(R)
または_Alignof(R)[p]
いいえ はい 該当なし
タイプof [q] typeof(a)
typeof(R)
typeof_unqual(a)
typeof_unqual(R)
該当なし はい 該当なし
辞典型[n] decltype (a)
decltype (R)
いいえ いいえ 該当なし
型識別 typeid(a)
typeid(R)
いいえ いいえ 該当なし
変換
(Cスタイルキャスト)
(R)a はい はい K::operator R();[5] 該当なし
変換[r] [6] R(a)
R{a}[n]
auto(a)[h]
auto{a}[h]
いいえ いいえ 該当なし
static_cast変換[s] static_cast<R>(a) はい いいえ K::operator R();
explicit K::operator R();[名詞]
該当なし
動的キャスト変換 dynamic_cast<R>(a) いいえ いいえ 該当なし
const_cast変換 const_cast<R>(a) いいえ いいえ 該当なし
reinterpret_cast変換 reinterpret_cast<R>(a) いいえ いいえ 該当なし
メモリを割り当てる new R[t] はい いいえ void* K::operator new(size_t x); void* operator new(size_t x);
配列を割り当てる new R[n][u] はい いいえ void* K::operator new[](size_t a); void* operator new[](size_t a);
メモリの割り当てを解除する delete a はい いいえ void K::operator delete(void* a); void operator delete(void* a);
配列の割り当てを解除する delete[] a はい いいえ void K::operator delete[](void* a); void operator delete[](void* a);
例外チェック[n] noexcept(a) いいえ いいえ 該当なし

同義語

C++では、いくつかの演算子の別名として機能するキーワードが定義されている: [7]

キーワード オペレーター
and &&
and_eq &=
bitand &
bitor |
compl ~
not !
not_eq !=
or ||
or_eq |=
xor ^
xor_eq ^=

各キーワードは演算子を指定するための異なる方法であり、対応する記号のバリエーションの代わりに使用できます。例えば、(a > 0 and not flag)と は(a > 0 && !flag)同じ動作を指定します。別の例として、キーワードはビット論理積演算子だけでなくアドレス演算子bitand置き換えにも使用でき、参照型(例: )の指定にも使用できますint bitand ref = n

ISO C仕様では、これらのキーワードをヘッダーファイル内のプリプロセッサマクロとして使用できますiso646.h。Cとの互換性のため、C++ではヘッダーファイルも提供されていますがiso646.h、これをインクルードしても効果はありません。C++20までは、対応するヘッダーファイルも提供されていましたが、ciso646これも効果はありませんでした。

式の評価順序

式の評価中、部分式の評価順序は優先順位結合性によって決定されます。優先順位の高い演算子は優先順位の低い演算子よりも先に評価され、演算子のオペランドは結合性に基づいて評価されます。次の表は、CおよびC++の演算子の優先順位と結合性を示しています。演算子は、優先順位が同じグループに分けられ、上から下に向かって降順で並べられています(順序が低いほど優先順位が高くなります)。[8] [9] [10]

演算子の優先順位はオーバーロードの影響を受けません。

注文 オペレーター 説明 結合性
1

最高

:: スコープ解決(C++のみ) なし
2 ++ 接尾辞インクリメント 左から右へ
-- 後置デクリメント
() 関数呼び出し
[] 配列の添え字
. 参照による要素選択
-> ポインタによる要素選択
typeid() 実行時型情報(C++のみ)(typeidを参照)
const_cast 型キャスト(C++のみ)(const_castを参照)
dynamic_cast 型キャスト(C++のみ)(動的キャストを参照)
reinterpret_cast 型キャスト(C++のみ)(reinterpret_castを参照)
static_cast 型キャスト(C++のみ)(static_castを参照)
3 ++ プレフィックス増分 右から左へ
-- プレフィックスデクリメント
+ 単項プラス
- 単項マイナス
! 論理否定
~ ビットごとのNOT(1の補数
(type) 型キャスト
* 間接参照(逆参照)
& 住所
sizeof サイズ
_Alignof アライメント要件(C11以降)
newnew[] 動的メモリ割り当て(C++のみ)
deletedelete[] 動的メモリ解放(C++ のみ)
4 .* メンバーへのポインタ(C++のみ) 左から右へ
->* メンバーへのポインタ(C++のみ)
5 * 乗算 左から右へ
/ 分割
% モジュロ(剰余)
6 + 追加 左から右へ
- 減算
7 << ビット左シフト 左から右へ
>> ビット単位の右シフト
8 <=> 3 者間比較( C++20で導入- C++ のみ) 左から右へ
9 < 未満 左から右へ
<= 以下
> より大きい
>= より大きいか等しい
10 == 等しい 左から右へ
!= 等しくない
11 & ビットAND 左から右へ
12 ^ ビット単位のXOR(排他的論理和) 左から右へ
13 | ビットOR(包含OR) 左から右へ
14 && 論理積 左から右へ
15 || 論理和 左から右へ
16 co_await コルーチン処理(C++のみ) 右から左へ
co_yield
17 ?: 三項条件演算子 右から左へ
= 直接割り当て
+= 合計による割り当て
-= 差額による割り当て
*= 製品別の割り当て
/= 商による割り当て
%= 残余財産による譲渡
<<= ビット左シフトによる代入
>>= ビット単位の右シフトによる代入
&= ビットANDによる代入
^= ビット単位のXORによる代入
|= ビットORによる代入
throw Throw 演算子 (例外のスロー、C++ のみ)
18

最低

, コンマ 左から右へ

詳細

この表は評価順序の大部分を説明するのに十分ですが、いくつかの詳細は説明されていません。三項演算子は、代入演算子やコンマ演算子よりも優先順位が高いと記載されているにもかかわらず、任意の式を中間オペランドとして使用できます。したがって、a ? b, c : dは と解釈されa ? (b, c) : d、意味のない とは解釈されません(a ? b), (c : d)。したがって、条件演算子の中間にある式(?との間:)は、括弧で囲まれているものとして解析されます。また、Cキャスト式の括弧で囲まれていない直後の結果を のオペランドにすることはできませんsizeof。したがって、sizeof (int) * xは と解釈され、(sizeof(int)) * xではありませんsizeof ((int) * x)

連鎖表現

優先順位テーブルは、括弧で明示的に指定されていない場合に、連鎖式での結合の順序を決定します。

  • 例えば、++x*3は何らかの優先規則がなければ曖昧になります。優先表は、xは*よりも++に強く「束縛」されていることを示しています。そのため、++ が何をしても(現在または後続のいずれであっても、下記参照)、それはxに対してのみ行われ、に対しては行われません。つまり、 は ( , ) と同等です。x*3++xx*3
  • 同様に、 の3*x++場合、接尾辞++は式全体が評価された後に作用するように設計されていますが、優先順位表から、xのみがインクリメントされ、 はインクリメントされないことがわかります。実際、式 ( , ) は、 tmp を一時的な値として評価されます。これは機能的に ( , , )のようなものと同等です3*xtmp=x++3*tmptmp=3*x++xtmp
優先順位と束縛
  • 優先順位や結合の問題を抽象化して、式 3+2*y[i]++ の図を検討してください。コンパイラの仕事は、この図を、複数の単項演算子 (3+( . )、2*( . )、( . )++、( . )[ i ] と呼ぶ) が y への結合を競合している式に解決することです。優先順位表の順序により、各演算子が作用する最終的な部分式が解決されます。( . )[ i ] は y にのみ作用し、( . )++ は y[i] にのみ作用し、2*( . ) は y[i]++ にのみ作用し、3+( . ) は 2*((y[i])++) に「のみ」作用します。各演算子がどの部分式に作用するかは優先順位表から明らかですが、各演算子がいつ作用するかは優先順位表では解決されないことに注意することが重要です。この例では、(.)++演算子は優先順位規則によりy[i]にのみ作用しますが、結合レベルだけでは後置++のタイミングは示されません((.)++演算子は式でy[i]が評価された後にのみ作用します)。

バインディング

CおよびC++における演算子の結合は、優先順位表ではなく、因数分解された言語文法によって規定されます。これにより、微妙な矛盾が生じます。例えば、Cでは条件式の構文は次のようになります。

論理和式?:条件    

C++ では次のようになります。

論理和式?:代入    

したがって、次の表現になります。

e = a < d ? a++ : a = d

は2つの言語で異なる方法で解析されます。C言語では、この式は構文エラーになります。なぜなら、C言語の代入式の構文は次のようになるからです。

単項式' = '代入  

C++ では次のように解析されます。

e = ( a < d ? a ++ : ( a = d ))          

これは有効な表現である。[11] [12]

関数呼び出しの引数式、変数代入、またはコンマ区切りリストでコンマ演算子を使用するには、括弧を使用する必要があります。[13] [14]たとえば、

int a = 1 b = 2 奇妙な変数= ( ++ a b )、d = 4 ;             

ビット演算子と等価演算子の優先順位に対する批判

ビット論理演算子の優先順位は批判されてきた。[15]概念的には、&と|は*や+のような算術演算子である。

は構文的に と解析されますが、は と解析されます。そのため、通常よりも頻繁に括弧を使用する必要があります。 a & b == 7a & (b == 7)a + b == 7(a + b) == 7

歴史的に、ビット演算子と論理演算子の間には構文上の区別はありませんでした。BCPL B 、初期のCでは、これらの演算子は存在しませんでした。代わりに、演算子は「真理値コンテキスト」(つまり、ブール値が期待される場合、例えば では論理演算子として動作しますが、 ではビット演算子として動作します)で使用されるかどうかによって意味が異なります。これは、既存のシステムとの下位互換性を維持するために保持されました。 [16]&& ||& |if (a==b & c) {...}c = a & b

さらに、C++ (およびそれ以降のバージョンの C) では、3 方向比較演算子を除いて、等価演算によって、概念的には 1 ビット (1 または 0) であるbool型値が生成されるため、「ビット単位」演算には適切に属しません。

注記

  1. ^ 剰余演算子は整数オペランドのみをサポートします。浮動小数点の場合は、次のような関数をfmod使用できます。
  2. ^ abcd intプレフィックスとポストフィックスを区別するためのダミーパラメータです。
  3. ^ C++20の3者間比較について
  4. ^ 戻り値の型として可能なもの: std::weak_orderingstd::strong_orderingおよびstd::partial_orderingがあり、これらはすべて に変換可能です。
  5. ^ ab C++ の iostreamのコンテキストでは、作成者はと をそれぞれ「put-to」または「ストリーム挿入」演算子と「get-from」または「ストリーム抽出」演算子と呼ぶことがよくあります。<<>>
  6. ^ C99標準によれば、負の数の右シフトは実装依存である。GCC [3]などのほとんどの実装では算術シフト(つまり符号拡張)が用いられるが、論理シフトも可能である。
  7. ^ C99標準によれば、負の数の右シフトは実装依存である。GCC [3]などのほとんどの実装では算術シフト(つまり符号拡張)が用いられるが、論理シフトも可能である。
  8. ^ abc C++23以降
  9. ^ オーバーロードされたオブジェクトの実際のアドレスはoperator &std::addressofで取得できます。
  10. ^ の戻り値の型は、ポインタ型など、演算を適用できる型でなければなりません。が 型でオーバーロードされている場合は に展開されますoperator->()->xCCoperator->()x->yx.operator->()->y
  11. ^ マイヤーズ、スコット(1999年10月)、「スマートポインタのためのoperator->*の実装」(PDF)Dr. Dobb's Journal、Aristeia
  12. ^ C23 時点では::C に句読点が存在しますが、スコープ解決演算子としては使用されません。
  13. ^ C++11 ユーザー定義リテラルについて
  14. ^ abcdefg C++11以降
  15. ^ 括弧は値のサイズを取得する際には必要ありません。型のサイズを取得する際にのみ必要です。ただし、通常はどちらであっても使用されます。[要出典]
  16. ^ C++ではalignof演算子が定義されていますが、Cでは定義されています_Alignof(C23では両方定義されています)。どちらの演算子も同じ意味を持ちます。
  17. ^ C23以降; 標準C++にはない
  18. ^ const_cast/static_cast/reinterpret_cast と同様に動作します。最後の2つのケースでは、指定子はそれぞれ または で宣言された変数 x の型(関数宣言として解釈されることはありません)autoに置き換えられます。auto x(a);auto x{a};
  19. ^ ユーザー定義の変換の場合、型が推論されない限り (など)、戻り値の型は暗黙的に、必然的に演算子名と一致しますoperator auto()operator decltype(auto)()
  20. ^ 初期化子が提供されている場合は、型名も推論できます (例)。new auto
  21. ^ 初期化子が提供されている場合は、配列のサイズも推測できます。

参照

  • C言語におけるビット演算 - 整数データ型の個々のビットを変換する演算
  • ビット操作 – ワードレベル以下のデータをアルゴリズム的に変更する
  • 論理演算子 – 論理式を連結する記号リダイレクト先の簡単な説明を表示するページ
  • ブール代数(論理)  - 「真」と「偽」の代数的操作リダイレクト先の簡単な説明を表示するページ
  • 論理記号表 – 論理関係を表すために使用される記号のリストリダイレクト先の簡単な説明を表示するページ

参考文献

  1. ^ 「演算子オーバーロード§比較演算子」cppreference.com
  2. ^ 「標準C++」。
  3. ^ ab 「整数実装」、GCC 4.3.3、GNU
  4. ^ 「ISO/IEC 9899:1999仕様、TC3」(PDF)。p. 64、§ 6.4.6ポンクチュエーター、パラグラフ3。
  5. ^ 「ユーザー定義変換」 。 2020年4月5日閲覧
  6. ^ C++における明示的な型変換
  7. ^ ISO/IEC 14882:1998(E) プログラミング言語 C++ . open-std.org – C++ 標準委員会. 1998年9月1日. pp.  40– 41.
  8. ^ ISO/IEC 9899:201x プログラミング言語 - C . open-std.org – C標準委員会. 2011年12月19日. p. 465.
  9. ^ ISO C 1999規格、セクション6.5.6注71(技術レポート)。ISO。1999。
  10. ^ 「C++ 組み込み演算子、優先順位、結合性」. docs.microsoft.com . 2020年5月11日閲覧
  11. ^ 「C演算子の優先順位 - cppreference.com」。en.cppreference.com 。 2020年4月10日閲覧
  12. ^ 「C/C++の三項演算子は実際には代入演算子と同じ優先順位を持つのか?」Stack Overflow 。 2019年9月22日閲覧
  13. ^ “その他の演算子 - cppreference.com”. en.cppreference.com . 2020年4月10日閲覧
  14. ^ 「c++ - カンマ演算子はどのように機能しますか?」Stack Overflow 。 2020年4月1日閲覧
  15. ^ Cの歴史 § 新生児C、ベル研究所
  16. ^ “Re^10: next unless condition”. www.perlmonks.org . 2018年3月23日閲覧
  • 「演算子」、C++ リファレンス (wiki)
  • C演算子の優先順位
  • 後置インクリメント演算子とデクリメント演算子: ++ と -- (開発者ネットワーク)、Microsoft、2021 年 8 月 17 日
「https://en.wikipedia.org/w/index.php?title=Operators_in_C_and_C%2B%2B&oldid=1331629870」より取得