Namespaces
Variants

Arithmetic operators

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

特定の算術演算の結果を返します。

演算子名 構文 プロトタイプ例 ( class T の場合)
クラス定義内 クラス定義外
単項プラス + a T T :: operator + ( ) const ; T operator + ( const T & a ) ;
単項マイナス - a T T :: operator - ( ) const ; T operator - ( const T & a ) ;
加算 a + b T T :: operator + ( const T2 & b ) const ; T operator + ( const T & a, const T2 & b ) ;
減算 a - b T T :: operator - ( const T2 & b ) const ; T operator - ( const T & a, const T2 & b ) ;
乗算 a * b T T :: operator * ( const T2 & b ) const ; T operator * ( const T & a, const T2 & b ) ;
除算 a / b T T :: operator / ( const T2 & b ) const ; T operator / ( const T & a, const T2 & b ) ;
剰余 a % b T T :: operator % ( const T2 & b ) const ; T operator % ( const T & a, const T2 & b ) ;
ビット単位NOT ~a T T :: operator ~ ( ) const ; T operator~ ( const T & a ) ;
ビット単位 AND a & b T T :: operator & ( const T2 & b ) const ; T operator & ( const T & a, const T2 & b ) ;
ビット単位の論理和 a | b T T :: operator | ( const T2 & b ) const ; T operator | ( const T & a, const T2 & b ) ;
ビット単位XOR a ^ b T T :: operator ^ ( const T2 & b ) const ; T operator ^ ( const T & a, const T2 & b ) ;
ビット単位左シフト a << b T T :: operator << ( const T2 & b ) const ; T operator << ( const T & a, const T2 & b ) ;
ビット単位右シフト a >> b T T :: operator >> ( const T2 & b ) const ; T operator >> ( const T & a, const T2 & b ) ;
注記
  • この表のすべての演算子は overloadable です。
  • すべての組み込み演算子は値を返し、ほとんどの user-defined overloads も値を返すため、ユーザー定義演算子を組み込み演算子と同じ方法で使用できます。ただし、ユーザー定義の演算子オーバーロードでは、あらゆる型を戻り値の型として使用できます( void を含む)。特に、 operator << operator >> のストリーム挿入およびストリーム抽出オーバーロードは T& を返します。
  • T2 T を含む任意の型を指定できます。

目次

概要説明

組み込みの算術演算子はすべて、特定の算術演算の結果を計算し、その結果を返します。引数は変更されません。

変換

組み込み算術演算子に渡されるオペランドが整数型またはスコープなし列挙型の場合、他のすべてのアクションの前(ただし該当する場合は左辺値から右辺値への変換の後)に、オペランドは 整数プロモーション を受けます。オペランドが配列型または関数型を持つ場合、 配列からポインタへの および 関数からポインタへの 変換が適用されます。

二項演算子(シフト演算子を除く)において、昇格後のオペランドの型が異なる場合、 通常の算術変換 が適用されます。

オーバーフロー

符号なし整数演算は常に 2 n
を法として実行されます。ここでnはその整数のビット数です。例: unsigned int の場合、 UINT_MAX に1を加算すると 0 となり、 0 から1を減算すると UINT_MAX となります。

符号付き整数の算術演算がオーバーフローした場合(結果が結果の型に収まらない)、その動作は未定義です。— このような演算の可能性のある現れ方には以下が含まれます:

  • それは表現の規則(一般的に 2の補数 )に従ってラップアラウンドします、
  • トラップする — 一部のプラットフォームまたはコンパイラオプションにより(例: -ftrapv in GCC and Clang)、
  • 最小値または最大値に飽和します(多くのDSPで)、
  • 完全に コンパイラによって最適化除去されます

浮動小数点環境

#pragma STDC FENV_ACCESS がサポートされており、かつ ON に設定されている場合、すべての浮動小数点算術演算子は現在の浮動小数点 丸め方向 に従い、 math_errhandling で指定されている通りに浮動小数点算術エラーを報告します。ただし、 静的初期化子 の一部である場合を除きます(その場合、浮動小数点例外は発生せず、丸めモードは最近接偶数丸めとなります)。

浮動小数点縮約

#pragma STDC FP_CONTRACT がサポートされておらず、かつ OFF に設定されていない限り、すべての浮動小数点演算は中間結果が無限の範囲と精度を持つかのように実行されてもよい。すなわち、丸め誤差や浮動小数点例外を省略する最適化が許可される。例えば、C++では ( x * y ) + z の実装を単一の融合積和演算CPU命令で行うことや、 a = x * x * x * x ; tmp = x * x ; a = tmp * tmp として最適化することが許可されている。

契約とは無関係に、浮動小数点演算の中間結果は、その型で示される範囲と精度とは異なる範囲と精度を持つ場合があります。詳細は FLT_EVAL_METHOD を参照してください。

形式的には、C++標準は浮動小数点演算の精度について保証を行いません。

単項算術演算子

単項算術演算子式の形式は以下の通りです

+ (1)
- (2)
1) 単項プラス(昇格)。
2) 単項マイナス(否定)。

単項演算子 + および - はすべての二項算術演算子より高い 優先順位 を持つため、 expression はトップレベルの二項算術演算子を含むことはできません。これらの演算子は右から左への結合性を持ちます:

+a - b; // (+a) - b と等価、+(a - b) ではない
-c + d; // (-c) + d と等価、-(c + d) ではない
+-e; // +(-e) と等価、単項演算子の + は「e」が組み込み型の場合には無効操作となる
     // なぜなら、あらゆる可能性のある昇格は否定演算中に既に実行されるため

組み込み単項算術演算子

1) 組み込みの単項プラス演算子の場合、 expression は算術型、スコープなし列挙型、またはポインタ型のprvalueでなければなりません。整数型またはスコープなし列挙型の場合、 expression に対して整数昇格が実行されます。結果の型は expression の(昇格された可能性のある)型となります。
組み込みプロモーションの結果は expression の値です。被演算子がプロモートされた整数型またはポインタ型のprvalueである場合、組み込み単項演算はno-opです。それ以外の場合、被演算子の型または値カテゴリは、整数プロモーション、lvalue-to-rvalue、array-to-pointer、function-to-pointer、またはユーザー定義変換によって変更されます。例えば、 char int に変換され、非ジェネリックでキャプチャなしの lambda expression は関数ポインタに変換されます (C++11以降) 単項プラス式で。
2) 組み込みの単項マイナス演算子について、 expression は算術型または非スコープ列挙型のprvalueでなければなりません。 expression に対して整数昇格が行われます。結果の型は、 expression の昇格後の型と同じ型になります。
組み込みの否定演算の結果は、昇格後の expression の負数です。符号なし a の場合、 - a の値は 2 N
-a
となります。ここで N は昇格後のビット数です。
  • 言い換えれば、結果はオペランドの2の補数です(オペランドと結果は符号なしとして扱われます)。

オーバーロード

ユーザー定義演算子に対するオーバーロード解決 において、すべてのCV修飾子なし昇格算術型 A およびすべての型 T について、以下の関数シグネチャがオーバーロード解決に参加します:

A operator + ( A )
T * operator + ( T * )
A operator - ( A )
(注:指定された要件に従い、HTMLタグ・属性、 タグ内のC++コードは一切翻訳せず、元のフォーマットを保持しています。C++固有の用語(operatorなど)も翻訳対象外としました)
#include <iostream>
int main()
{
    char c = 0x6a;
    int n1 = 1;
    unsigned char n2 = 1;
    unsigned int n3 = 1;
    std::cout << "char: " << c << " int: " << +c << "\n"
                 "-1, where 1 is signed: " << -n1 << "\n"
                 "-1, where 1 is unsigned char: " << -n2 << "\n"
                 "-1, where 1 is unsigned int: " << -n3 << '\n';
    char a[3];
    std::cout << "size of array: " << sizeof a << "\n"
                 "size of pointer: " << sizeof +a << '\n';
}

出力例:

char: j int: 106
-1, where 1 is signed: -1
-1, where 1 is unsigned char: -1
-1, where 1 is unsigned int: 4294967295
size of array: 3
size of pointer: 8

加算演算子

加算演算子の式は以下の形式を持ちます

lhs + rhs (1)
lhs - rhs (2)
1) 二項プラス(加算)。
2) 二項マイナス(減算)。

二項演算子 + および - は、 * / % を除く他のすべての二項算術演算子よりも高い 優先順位 を持ちます。これらの演算子は左から右へ結合します:

a + b * c;  // a + (b * c) と等価、(a + b) * c ではない
d / e - f;  // (d / e) - f と等価、d / (e - f) ではない
g + h >> i; // (g + h) >> i と等価、g + (h >> i) ではない
j - k + l - m; // ((j - k) + l) - m と等価

組み込み加算演算子

組み込みの二項プラス演算子および二項マイナス演算子では、 lhs rhs の両方がprvalueである必要があり、以下の条件のいずれかを満たさなければなりません:

  • 両方のオペランドが算術型または非スコープ列挙型を持つ場合。 この場合、 通常の算術変換 が両方のオペランドに対して実行されます。
  • 厳密に一方のオペランドのみが整数型または非スコープ列挙型を持つ場合。 この場合、そのオペランドに対して整数昇格が適用されます。

このセクションの残りの説明において、「オペランド」、 lhs および rhs は、変換または昇格されたオペランドを指します。

1) 組み込みの加算演算子では、以下のいずれかの条件を満たす必要があります:
  • 両方のオペランドが算術型を持つ。この場合、結果はオペランドの和となります。
  • 一方のオペランドが完全に定義されたオブジェクト型へのポインタで、もう一方のオペランドが整数型を持つ。この場合、整数値がポインタに加算されます( ポインタ演算 を参照)。
2) 組み込みの減算演算子では、以下のいずれかの条件を満たす必要があります:
  • 両オペランドが算術型を持つ場合。この場合、結果は lhs から rhs を減算した差となります。
  • lhs が完全に定義されたオブジェクト型へのポインタであり、 rhs が整数型を持つ場合。この場合、整数値がポインタから減算されます( ポインタ演算 を参照)。
  • 両オペランドが、同じ完全に定義されたオブジェクト型のcv修飾版またはcv非修飾版へのポインタである場合。この場合、 rhs lhs から減算されます( ポインタ演算 を参照)。

両方のオペランドが浮動小数点型を持ち、かつその型がIEEE浮動小数点演算をサポートしている場合( std::numeric_limits::is_iec559 を参照):

  • 一方のオペランドがNaNの場合、結果はNaNです。
  • 無限大から無限大を減算するとNaNとなり、 FE_INVALID が発生します。
  • 無限大と負の無限大を加算するとNaNとなり、 FE_INVALID が発生します。

ポインタ演算

整数型の式 J がポインタ型の式 P に加算または減算されるとき、結果は P の型を持ちます。

  • P ヌルポインタ値 に評価され、かつ J 0 に評価される場合、結果はヌルポインタ値となる。
  • それ以外の場合、 P n 個の要素を持つ配列オブジェクト x i 番目の要素を指し、 J の値が j であるとき、 P は以下のように加算または減算される:
  • P + J および J + P
  • i+j 番目の要素を指す( i + j [ 0 , n ) の範囲内にある場合)
  • x の最後の要素の次を指す( i + j n に等しい場合)
  • P - J
  • i-j 番目の要素を指す( i - j [ 0 , n ) の範囲内にある場合)
  • x の最後の要素の次を指す( i - j n に等しい場合)
  • その他の j の値は未定義動作を引き起こす。
  • それ以外の場合、 P が完全オブジェクト、基底クラスのサブオブジェクト、またはメンバーサブオブジェクト y を指す場合、 J の値が j として与えられるとき、 P は以下のように加算または減算されます:
  • P + J および J + P
  • j 0 の場合、 y を指し、
  • j 1 の場合、 y の終端を過ぎた位置を指す。
  • P - J
  • j 0 の場合、 y を指し、
  • j - 1 の場合、 y の終端を過ぎた位置を指す。
  • その他の j の値は未定義動作を引き起こす。
  • それ以外の場合、 P がオブジェクト z の終端を過ぎたポインタであり、 J の値が j として与えられる場合:
  • もし z n 個の要素を持つ配列オブジェクトである場合、 P は以下のように加算または減算されます:
  • P + J および J + P
  • n + j [ 0 , n ) の範囲内にある場合、 z n+j 番目の要素を指し、
  • j 0 の場合、 z の最後の要素の終端を超えたポインタとなります。
  • P - J
  • n - j [ 0 , n ) の範囲内にある場合、 z n-j 番目の要素を指し、
  • j 0 の場合、 z の最後の要素の終端を超えたポインタとなります。
  • その他の j の値は未定義動作を引き起こします。
  • それ以外の場合、 P は以下のように加算または減算されます:
  • P + J および J + P
  • j - 1 の場合、 z を指し、
  • j 0 の場合、 z の終端を超えたポインタとなります。
  • P - J
  • j 1 の場合、 z を指し、
  • j 0 の場合、 z の終端を超えたポインタとなります。
  • その他の j の値は未定義動作を引き起こします。
  • それ以外の場合、動作は未定義です。

2つのポインタ式 P Q が減算されるとき、結果の型は std::ptrdiff_t です。

  • P Q の両方が ヌルポインタ値 と評価される場合、結果は 0 となる。
  • それ以外の場合、 P Q がそれぞれ同じ配列オブジェクト x i 番目と j 番目の配列要素を指す場合、式 P - Q の値は i − j となる。
  • i − j std::ptrdiff_t で表現できない場合、動作は未定義です。
  • それ以外の場合、 P Q が同じ完全オブジェクト、基底クラスの部分オブジェクト、またはメンバーの部分オブジェクトを指す場合、結果は 0 となる。
  • それ以外の場合、動作は未定義である。

これらのポインタ演算演算子は、ポインタが LegacyRandomAccessIterator 要件を満たすことを可能にします。

加算および減算において、 P または Q が「(possibly cv-qualified) T へのポインタ」型を持ち、 T と配列要素型が similar でない場合、動作は未定義です:

int arr[5] = {1, 2, 3, 4, 5};
unsigned int *p = reinterpret_cast<unsigned int*>(arr + 1);
unsigned int k = *p; // OK、「k」の値は2
unsigned int *q = p + 1; // 未定義動作:「p」はunsigned intではなくintを指している

オーバーロード

ユーザー定義演算子に対するオーバーロード解決 において、昇格された算術型の各ペア L R 、およびオブジェクト型 T ごとに、以下の関数シグネチャがオーバーロード解決に参加します:

LR operator + ( L, R )
LR operator - ( L, R )
T * operator + ( T * , std:: ptrdiff_t )
T * operator + ( std:: ptrdiff_t , T * )
T * operator - ( T * , std:: ptrdiff_t )
std:: ptrdiff_t operator - ( T * , T * )

LR L R に対する 通常の算術変換 の結果です。

#include <iostream>
int main()
{
    char c = 2;
    unsigned int un = 2;
    int n = -10;
    std::cout << " 2 + (-10), where 2 is a char    = " << c + n << "\n"
                 " 2 + (-10), where 2 is unsigned  = " << un + n << "\n"
                 " -10 - 2.12  = " << n - 2.12 << '\n';
    char a[4] = {'a', 'b', 'c', 'd'};
    char* p = &a[1];
    std::cout << "Pointer addition examples: " << *p << *(p + 2)
              << *(2 + p) << *(p - 1) << '\n';
    char* p2 = &a[4];
    std::cout << "Pointer difference: " << p2 - p << '\n';
}

出力:

 2 + (-10), where 2 is a char    = -8
 2 + (-10), where 2 is unsigned  = 4294967288
 -10 - 2.12  = -12.12
Pointer addition examples: bdda
Pointer difference: 3

乗算演算子

乗算演算子の式は以下の形式を持ちます

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
**注記:** - HTMLタグ、属性、 タグ内のテキストは翻訳対象外 - C++専門用語(lhs, rhs)は翻訳対象外 - 数式の構造とフォーマットは完全に保持
1) 乗算。
2) 除算。
3) 剰余。

乗法演算子は他のすべての二項算術演算子より高い 優先順位 を持ちます。これらの演算子は左から右へ結合します:

a + b * c;  // a + (b * c) と等価、(a + b) * c ではない
d / e - f;  // (d / e) - f と等価、d / (e - f) ではない
g % h >> i; // (g % h) >> i と等価、g % (h >> i) ではない
j * k / l % m; // ((j * k) / l) % m と等価

組み込み乗法演算子

組み込みの乗算演算子および除算演算子では、両方のオペランドが算術型または非スコープ列挙型でなければなりません。組み込みの剰余演算子では、両方のオペランドが整数型または非スコープ列挙型でなければなりません。 通常の算術変換 が両方のオペランドに対して実行されます。

このセクションの残りの説明において、「オペランド」、 lhs および rhs は変換後のオペランドを指します。

1) 組み込み乗算の結果はオペランドの積です。
両方のオペランドが浮動小数点型を持ち、その型がIEEE浮動小数点演算をサポートしている場合( std::numeric_limits::is_iec559 を参照):
  • NaNと任意の数値の乗算はNaNを生成します。
  • 無限大とゼロの乗算はNaNを生成し、 FE_INVALID が発生します。
2) 組み込み除算の結果は lhs rhs で割った値です。 rhs がゼロの場合、動作は未定義です。
両方のオペランドが整数型を持つ場合、結果は代数的商(整数除算を実行)となります:商はゼロ方向に切り捨てられます(小数部分は破棄されます)。
両方のオペランドが浮動小数点型を持ち、その型がIEEE浮動小数点演算をサポートしている場合( std::numeric_limits::is_iec559 を参照):
  • 一方のオペランドがNaNの場合、結果はNaNとなります。
  • 非ゼロの数を±0.0で除算すると、正しい符号の無限大が得られ、 FE_DIVBYZERO が発生します。
  • 0.0を0.0で除算するとNaNが得られ、 FE_INVALID が発生します。
3) 組み込み剰余演算の結果は、 lhs rhs で整数除算した剰余である。 rhs がゼロの場合、動作は未定義である。
もし a / b が結果の型で表現可能であれば、 ( a / b ) * b + a % b == a が成り立つ。
a / b が結果型で表現できない場合、 a / b および a % b の両方の動作は未定義です(つまり、2の補数システムでは INT_MIN % - 1 は未定義です)。

注記: CWG issue 614 が解決されるまで ( N2757 )、二項演算子 % の一方または両方のオペランドが負の場合、剰余の符号は処理系定義でした。これは整数除算の丸め方向に依存するためです。この場合、 std::div 関数は明確に定義された動作を提供します。

注: 浮動小数点剰余については、 std::remainder および std::fmod を参照してください。

オーバーロード

ユーザー定義演算子に対するオーバーロード解決 において、すべての昇格された算術型の組 LA RA 、およびすべての昇格された整数型の組 LI RI について、以下の関数シグネチャがオーバーロード解決に参加します:

LRA operator * ( LA, RA )
LRA operator / ( LA, RA )
LRI operator % ( LI, RI )

where LRx is the result of usual arithmetic conversions on Lx and Rx .

#include <iostream>
int main()
{
    char c = 2;
    unsigned int un = 2;
    int  n = -10;
    std::cout << "2 * (-10), where 2 is a char    = " << c * n << "\n"
                 "2 * (-10), where 2 is unsigned  = " << un * n << "\n"
                 "-10 / 2.12  = " << n / 2.12 << "\n"
                 "-10 / 21  = " << n / 21 << "\n"
                 "-10 % 21  = " << n % 21 << '\n';
}

出力:

2 * (-10), where 2 is a char    = -20
2 * (-10), where 2 is unsigned  = 4294967276
-10 / 2.12  = -4.71698
-10 / 21  = 0
-10 % 21  = -10

ビット論理演算子

ビット単位論理演算子の式は以下の形式を持ちます

~ rhs (1)
lhs & rhs (2)
lhs | rhs (3)
lhs ^ rhs (4)
**注記:** - HTMLタグ、属性、 タグ内のテキストは翻訳対象外 - C++専門用語(lhs, rhs)は翻訳対象外 - 元の書式と構造を完全に保持
1) ビット単位NOT。
2) ビット単位のAND。
3) ビット単位のOR。
4) ビット単位XOR。

ビット単位NOT演算子はすべての二項算術演算子より 優先順位 が高くなります。右から左への結合性を持ちます:

~a - b; // (~a) - b と等価、~(a - b) ではない
~c * d; // (~c) * d と等価、~(c * d) ではない
~-e; // ~(-e) と等価

~ の後に 型名 または decltype 指定子 (C++11以降) が続く場合、文法上曖昧性が生じます。これは ~ がoperator~として解釈されるか、あるいは デストラクタ 識別子の開始となる可能性があるためです。この曖昧性は ~ をoperator~として扱うことで解決されます。 ~ がデストラクタ識別子として解釈されるのは、operator~の形成が構文的に不可能な場合のみです。

他のすべてのビット単位論理演算子は、他のすべての二項算術演算子より 優先順位 が低くなります。ビット単位ANDはビット単位XORより優先順位が高く、ビット単位XORはビット単位ORより優先順位が高くなります。これらは左から右へ結合します:

a & b * c;  // a & (b * c) と等価、(a & b) * c ではない
d / e ^ f;  // (d / e) ^ f と等価、d / (e ^ f) ではない
g << h | i; // (g << h) | i と等価、g << (h | i) ではない
j & k & l; // (j & k) & l と等価
m | n ^ o  // m | (n ^ o) と等価

組み込みビット論理演算子

組み込みのビット単位NOT演算子の場合、 rhs は整数型または非スコープ列挙型のprvalueでなければならず、 rhs に対して整数昇格が実行されます。他の組み込みビット単位論理演算子の場合、両オペランドは整数型または非スコープ列挙型でなければならず、両オペランドに対して 通常の算術変換 が実行されます。

このセクションの残りの説明において、「オペランド」、 lhs および rhs は、変換または昇格されたオペランドを指します。

1) オペランドを x とし、組み込みビット単位NOT演算の結果を r とする。 x の2進表現の各係数 x_i について、 r の2進表現の対応する係数 r_i は、 x_i 0 の場合 1 であり、それ以外の場合 0 となる。
  • 言い換えると、結果はオペランドの1の補数である(オペランドと結果は符号なしとして扱われる)。
結果の型 r はオペランド x の型と同じです。
2-4) オペランドがそれぞれ x y で、組み込み二項ビット論理演算の結果が r である場合。 x y の2進数表現における各係数の組 x_i y_i に対して、対応する r の2進数表現の係数 r_i
2) 1 x_iとy_iの両方が x_i y_i が共に 1 の場合、それ以外の場合は 0 となります。
3) 1 x_i y_i の少なくとも一方が 1 の場合、それ以外の場合は 0 となります。
4) 1 x_i y_i のいずれか一方(両方ではない)が 1 の場合、それ以外の場合は 0 となります。
結果の型 r はオペランド x および y の型と同じです。

オーバーロード

ユーザー定義演算子に対するオーバーロード解決 において、昇格された整数型の各ペア L R について、以下の関数シグネチャがオーバーロード解決に参加します:

R operator~ ( R )
LR operator & ( L, R )
LR operator ^ ( L, R )
LR operator | ( L, R )

LR L R に対する 通常の算術変換 の結果です。

#include <bitset>
#include <cstdint>
#include <iomanip>
#include <iostream>
int main()
{
    std::uint16_t mask = 0x00f0;
    std::uint32_t x0 = 0x12345678;
    std::uint32_t x1 = x0 | mask;
    std::uint32_t x2 = x0 & ~mask;
    std::uint32_t x3 = x0 & mask;
    std::uint32_t x4 = x0 ^ mask;
    std::uint32_t x5 = ~x0;
    using bin16 = std::bitset<16>;
    using bin32 = std::bitset<32>;
    std::cout << std::hex << std::showbase
              << "Mask: " << mask << std::setw(49) << bin16(mask) << "\n"
                 "Value: " << x0 << std::setw(42) << bin32(x0) << "\n"
                 "Setting bits: " << x1 << std::setw(35) << bin32(x1) << "\n"
                 "Clearing bits: " << x2 << std::setw(34) << bin32(x2) << "\n"
                 "Selecting bits: " << x3 << std::setw(39) << bin32(x3) << "\n"
                 "XOR-ing bits: " << x4 << std::setw(35) << bin32(x4) << "\n"
                 "Inverting bits: " << x5 << std::setw(33) << bin32(x5) << '\n';
}

出力:

Mask: 0xf0                                 0000000011110000
Value: 0x12345678          00010010001101000101011001111000
Setting bits: 0x123456f8   00010010001101000101011011111000
Clearing bits: 0x12345608  00010010001101000101011000001000
Selecting bits: 0x70       00000000000000000000000001110000
XOR-ing bits: 0x12345688   00010010001101000101011010001000
Inverting bits: 0xedcba987 11101101110010111010100110000111

ビットシフト演算子

ビット単位シフト演算子の式は以下の形式を持ちます

lhs << rhs (1)
lhs >> rhs (2)
1) ビット単位の左シフト。
2) ビット単位の右シフト。

ビットシフト演算子はビット論理演算子より 優先順位 が高いですが、加算演算子と乗算演算子よりは低い優先順位を持ちます。これらの演算子は左から右への結合性を持ちます:

a >> b * c;  // a >> (b * c) と等価、(a >> b) * c ではない
d << e & f;  // (d << e) & f と等価、d << (e & f) ではない
g << h >> i; // (g << h) >> i と等価、g << (h >> i) ではない

組み込みビットシフト演算子

組み込みのビットシフト演算子では、両方のオペランドが整数型またはスコープなし列挙型のprvalueでなければなりません。両方のオペランドに対して整数昇格が実行されます。

このセクションの残りの説明において、「オペランド」、 a b lhs および rhs は、変換または昇格されたオペランドを指します。

rhs の値が負であるか、または lhs のビット数より小さくない場合、動作は未定義です。

符号なし a の場合、 a << b の値は a * 2 b
の値を 2 N
を法として還元した値である(つまり、ビット単位の左シフトが実行され、宛先型からシフトアウトされたビットは破棄される)。

符号付きで非負の a の場合、 a * 2 b
が戻り値の型の符号なしバージョンで表現可能であれば、その値を符号付きに 変換 したものが a << b の値となる(これにより INT_MIN 1 << 31 として作成することが合法となる)。そうでない場合、動作は未定義である。

負の a の場合、 a << b の動作は未定義である。

符号なし a および符号付きで非負の a の場合、 a >> b の値は a/2 b
の整数部分である。

負の a の場合、 a >> b の値は処理系定義である(ほとんどの実装では、算術右シフトが実行され、結果は負のままとなる)。

(C++20まで)

a << b の値は、 a * 2 b
2 N
を法として合同な唯一の値である(つまり、ビット単位の左シフトが実行され、宛先型からシフトアウトされたビットは破棄される)。

a >> b の値は a/2 b
であり、負の無限大に向かって丸められる(言い換えれば、符号付き a に対する右シフトは算術右シフトである)。

(C++20から)

結果の型は lhs の型となります。

オーバーロード

ユーザー定義演算子に対するオーバーロード解決 において、昇格された整数型の各ペア L R について、以下の関数シグネチャがオーバーロード解決に参加します:

L operator << ( L, R )
L operator >> ( L, R )
#include <iostream>
enum { ONE = 1, TWO = 2 };
int main()
{
    std::cout << std::hex << std::showbase;
    char c = 0x10;
    unsigned long long ull = 0x123;
    std::cout << "0x123 << 1 = " << (ull << 1) << "\n"
                 "0x123 << 63 = " << (ull << 63) << "\n" // unsignedでのオーバーフロー
                 "0x10 << 10 = " << (c << 10) << '\n';   // charはintに昇格
    long long ll = -1000;
    std::cout << std::dec << "-1000 >> 1 = " << (ll >> ONE) << '\n';
}

出力:

0x123 << 1 = 0x246
0x123 << 63 = 0x8000000000000000
0x10 << 10 = 0x4000
-1000 >> 1 = -500

標準ライブラリ

算術演算子は多くの標準ライブラリ型に対してオーバーロードされています。

単項算術演算子

単項+および単項-を実装する
( std::chrono::duration<Rep,Period> の公開メンバ関数)
複素数に単項演算子を適用する
(関数テンプレート)
単項算術演算子をvalarrayの各要素に適用する
( std::valarray<T> の公開メンバ関数)

加算演算子

時間点を含む加算および減算演算を実行する
(関数テンプレート)
時間間隔を引数とする算術演算を実装する
(関数テンプレート)
year_month_day と年数または月数の加算または減算を行う
(関数)
2つの文字列、文字列と char 、または文字列と string_view を連結する
(関数テンプレート)
イテレータを進めるまたは戻す
( std::reverse_iterator<Iter> の公開メンバ関数)
イテレータを進めるまたは戻す
( std::move_iterator<Iter> の公開メンバ関数)
2つの複素数値、または複素数とスカラーの複素数算術演算を実行する
(関数テンプレート)
2つのvalarray、またはvalarrayと値の各要素に二項演算子を適用する
(関数テンプレート)

乗算演算子

期間を引数とする算術演算を実装する
(関数テンプレート)
2つの複素数値、または複素数とスカラーの複素数演算を実行する
(関数テンプレート)
2つのvalarray、またはvalarrayと値の各要素に二項演算子を適用する
(関数テンプレート)

ビット論理演算子

二項AND、OR、XORおよびNOTを実行する
( std::bitset<N> の公開メンバ関数)
bitsetに対して二項論理演算を実行する
(関数テンプレート)
単項算術演算子をvalarrayの各要素に適用する
( std::valarray<T> の公開メンバ関数)
二つのvalarray、またはvalarrayと値に対して二項演算子を各要素に適用する
(関数テンプレート)

ビット単位シフト演算子

二つのvalarray、またはvalarrayと値の各要素に二項演算子を適用する
(関数テンプレート)
バイナリ左シフトと右シフトを実行する
( std::bitset<N> の公開メンバ関数)

ストリーム挿入/抽出演算子

標準ライブラリ全体において、ビット単位シフト演算子は一般的にI/Oストリーム( std:: ios_base & またはその派生クラスのいずれか)を左オペランドおよび戻り値の型としてオーバーロードされます。このような演算子は ストリーム挿入 演算子および ストリーム抽出 演算子として知られています:

書式化データを抽出
( std::basic_istream<CharT,Traits> の公開メンバ関数)
文字および文字配列を抽出
(関数テンプレート)
書式化データを挿入
( std::basic_ostream<CharT,Traits> の公開メンバ関数)
文字データを挿入、または右辺値ストリームへ挿入
(関数テンプレート)
複素数のシリアライズとデシリアライズを実行
(関数テンプレート)
ビットセットのストリーム入出力を実行
(関数テンプレート)
文字列のストリーム入出力を実行
(関数テンプレート)
擬似乱数エンジンのストリーム入出力を実行
(関数テンプレート)
擬似乱数分布のストリーム入出力を実行
(関数テンプレート)

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
CWG 614 C++98 整数除算の代数的商は
実装定義の方向に丸められていた
整数除算の代数的商は
ゼロ方向に切り捨てられる
(小数部は破棄される)
CWG 1450 C++98 a / b の結果が結果型で表現できない場合、
その結果は未規定であった
この場合、 a / b
a % b の両方の動作は未定義となる
CWG 1457 C++98 正の符号付き値の最左ビット 1
符号ビットにシフトする動作は未定義であった
明確に定義された
CWG 1504 C++98 配列要素の基底クラス部分オブジェクトへのポインタを
ポインタ演算で使用できた
この場合の動作は
未定義となる
CWG 1515 C++98 unsigned で宣言された符号なし整数のみが
算術の法則 モジュロ 2 n
に従うべきであった
全ての符号なし整数に適用される
CWG 1642 C++98 算術演算子はその被演算子を左辺値として許可していた 一部の被演算子は右辺値でなければならない
CWG 1865 C++98 CWG issue 1504 の解決により、
配列要素へのポインタを含むポインタ演算の動作が、
指し示す型と配列要素型の非トップレベルでの
cv修飾が異なる場合に未定義となった
明確に定義された
CWG 1971 C++98 ~ の曖昧性を解決するルールが
~X ( 0 ) のようなケースに適用されるか不明確であった
このルールはそのようなケースに適用される
CWG 2419 C++98 非配列オブジェクトへのポインタは、
サイズ1の配列の先頭要素へのポインタとして
ポインタ演算で扱われるのは、 & で取得されたポインタのみであった
全ての非配列オブジェクトへの
ポインタに適用される
CWG 2626 C++98 組み込み operator~ の結果は単に
'1の補数'とされ、適切な定義がなかった
結果は基数2表現の
観点で表現される
CWG 2724 C++20 算術右シフトの丸め方向が不明確であった 明確にされた
CWG 2853 C++98 オブジェクトの終端を超えるポインタは
整数との加算・減算ができなかった
可能となった

関連項目

演算子の優先順位

演算子のオーバーロード

HTMLタグと属性、および` `タグ内のC++コードは翻訳せず、元のフォーマットを保持しました。「comma」のみを「カンマ」に翻訳しました。
共通演算子
代入 インクリメント
デクリメント
算術 論理 比較 メンバー
アクセス
その他

a = b
a + = b
a - = b
a * = b
a / = b
a % = b
a & = b
a | = b
a ^ = b
a <<= b
a >>= b

++ a
-- a
a ++
a --

+ a
- a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

! a
a && b
a || b

a == b
a ! = b
a < b
a > b
a <= b
a >= b
a <=> b

a [ ... ]
* a
& a
a - > b
a. b
a - > * b
a. * b

関数呼び出し

a ( ... )
カンマ

a, b
条件演算子

a ? b : c
特殊演算子

static_cast 関連する型間で変換を行う
dynamic_cast 継承階層内で変換を行う
const_cast cv 修飾子の追加または削除を行う
reinterpret_cast 無関係な型間で変換を行う
Cスタイルキャスト static_cast const_cast reinterpret_cast の組み合わせで型変換を行う
new 動的ストレージ期間を持つオブジェクトを作成する
delete new式で作成されたオブジェクトを破棄し、確保されたメモリ領域を解放する
sizeof 型のサイズを問い合わせる
sizeof... パック のサイズを問い合わせる (C++11以降)
typeid 型の型情報を問い合わせる
noexcept 式が例外をスローできるかどうかをチェックする (C++11以降)
alignof 型のアライメント要件を問い合わせる (C++11以降)

C documentation for Arithmetic operators
日本語訳:
Cドキュメント for 算術演算子
注記: - HTMLタグ、属性、class名はそのまま保持 - "C documentation" → "Cドキュメント"(C++用語として保持) - "Arithmetic operators" → "算術演算子"(専門用語の適切な訳) - "for"は文脈上そのまま保持(前置詞としての機能を考慮)