Aritmetikai operátorok

C++ nyelv

Általános témák
Flow control
Conditional végrehajtási utasítások

if

Iterációs utasítások (ciklusok)

for

tartomány-for (C++11)

Ugrás utasítások

continuebreak

gotoreturn

Functions
Function declaration
Lambda function declaration
inline specifier
Exception specifications (until C++20)
. noexcept specifikáló (C++11)
Kivételek
Névterek
Típusok
Specifikátorok

decltype (C++11)

auto (C++11)

alignas (C++11)


const/volatile

constexpr (C++11)

Tárolási időtartam meghatározók
Inicializálás
Kifejezések
Alternatív ábrázolások
Literálisok
Boolean – Egész szám – Lebegőpontos
Karakter – Karakterlánc – nullptr (C++11)
Felhasználó-definiált (C++11)
Segédprogramok
Attribútumok (C++11)
Típusok
typedef deklaráció
Típus alias deklaráció (C++11)
Casts
Implicit konverziók -. Explicit konverziók
static_castdynamic_cast
const_castdynamic_cast
const_castreinterpret_cast
Memória kiosztás
Osztályok
Osztály-specifikus függvénytulajdonságok

Virtuális függvény

override specifikáló (C++11)

final specifikáló (C++11)

explicit (C++11)

static

Speciális tagfüggvények

Másolás hozzárendelés

Mozgás hozzárendelés (C++11)

Destruktor

Sablonok

Sablon specializáció

Paramétercsomagok (C++11)

Egyéb
Kifejezések

Általános

értékkategóriák (lvalue, rvalue, xvalue)

kiértékelés sorrendje (sorrendi pontok)

konstans kifejezések

kiértékeletlen kifejezések

elsődleges kifejezések

lambda-kifejezés(C++11)

literálok

integer literálok

floating-pont literálok

boolean literálok

karakter literálok, beleértve az escape szekvenciákat

string literálok

null pointer literál(C++11)

user-defined literál(C++11)

operátorok

hozzárendelési operátorok: a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b

Inkrementálás és dekrementálás: ++a, --a, a++, a--

Aritmetikai operátorok: +a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b

Logikai operátorok: a||b, a&&b, !a

Összehasonlító operátorok: a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)

Tag hozzáférési operátorok: a, *a, &a, a->b, a.b, a->*b, a.*b

Egyéb operátorok: a(...), a,b, a?b:c

new-kifejezés

delete-kifejezés

throw-kifejezés

alignof

sizeof

sizeof…(C++11)

typeid

noexcept(C++11)

Fold expression(C++17)

Operátorok alternatív ábrázolása

Precedence és asszociativitás

Operátorok túlterhelése

. Alapértelmezett összehasonlítások(C++20)

Konverziók

Implicit konverziók

const_cast

static_cast

reinterpret_cast

dynamic_cast

Explicit konverziók (T)a, T(a)

Felhasználó által definiált konverzió

Egy adott aritmetikai művelet eredményét adja vissza.

Operátor neve Szintaxis Túlterhelhető Prototípus példák (T osztályhoz)
Az osztály definícióján belül Az osztály definícióján kívül
unary plus +a Yes T T::operator+() const; T operator+(const T &a);
unary minus -a Yes T T::operator-() const; T operator-(const T &a);
addition a + b Yes T T::operator+(const T2 &b) const; T operator+(const T &a, const T2 &b);
subtraction a - b Yes T T::operator-(const T2 &b) const; T operator-(const T &a, const T2 &b);
szorzás a * b Igen T T::operator*(const T2 &b) const; T operator*(const T &a, const T2 &b);
division a / b Yes T T::operator/(const T2 &b) const; T operator/(const T &a, const T2 &b);
modulo a % b Igen T T::operator%(const T2 &b) const; T operator%(const T &a, const T2 &b);
bitwise NOT ~a Yes T T::operator~() const; T operator~(const T &a);
bitwise AND a & b Yes T T::operator&(const T2 &b) const; T operator&(const T &a, const T2 &b);
bitwise OR a | b Yes T T::operator|(const T2 &b) const; T operator|(const T &a, const T2 &b);
bitwise XOR a ^ b Yes T T::operator^(const T2 &b) const; T operator^(const T &a, const T2 &b);
bitwise left shift a << b Yes T T::operator<<(const T2 &b) const; T operator<<(const T &a, const T2 &b);
bitwise right shift a >> b Yes T T::operator>>(const T2 &b) const; T operator>>(const T &a, const T2 &b);
Megjegyzések

  • Minden beépített operátor értéket ad vissza, és a legtöbb felhasználó által definiált túlterhelés is értéket ad vissza, így a felhasználó által definiált operátorok ugyanúgy használhatók, mint a beépítettek. Egy felhasználó által definiált operátor túlterhelésben azonban bármilyen típus használható visszatérési típusként (beleértve a void-ot is). Különösen a operator<< és operator>> folyambeillesztés és folyamkivonás túlterhelésének visszatérési értéke T&.
  • T2 bármilyen típus lehet, beleértve a T

  • 1 Magyarázat
    • 1.1 Átváltások
    • 1.2 Túlcsordulások
    • 1.3 Lebegőpontos környezet
    • 1.4 Lebegőpontos kontrakció
    • 1.5 Unáris aritmetikai operátorok
    • 1.6 Additív operátorok
    • 1.7 Multiplikatív operátorok
    • 1.8 Bitenkénti logikai operátorok
    • 1.9 Bitenkénti eltolási operátorok
  • 2 Standard könyvtár
    • 2.1 Unáris aritmetikai operátorok
    • 2.2 Additív operátorok
    • 2.3 Multiplikatív operátorok
    • 2.4 Bitenkénti logikai operátorok
    • 2.5 Bitenkénti eltolási operátorok
    • 2.6 Patakbeillesztési/kivonási operátorok
  • 3 Hibajelentések
  • 4 Lásd még

Magyarázat

Minden aritmetikai operátor kiszámítja egy adott aritmetikai művelet eredményét és visszaadja annak eredményét. Az argumentumok nem módosulnak.

Konverziók

Ha az aritmetikai operátornak átadott operandus integrál vagy nem skopált felsorolás típusú, akkor minden más művelet előtt (de az l-érték-r-érték konverzió után, ha alkalmazható) az operandus integrál előléptetésen megy keresztül. Ha az operandus tömb- vagy függvénytípusú, akkor tömb-mutató és függvény-mutató konverziókat alkalmazunk.

A bináris operátorok esetében (kivéve az eltolásokat), ha az előléptetett operandusok különböző típusúak, további implicit konverziókat alkalmazunk, amelyeket szokásos aritmetikai konverzióknak nevezünk, és amelyek célja a közös típus előállítása (amely az std::common_type típusjellemzőn keresztül is elérhető). Ha bármely integrál előléptetés előtt az egyik operandus felsorolás típusú, a másik operandus pedig lebegőpontos típusú vagy más felsorolás típusú, akkor ez a viselkedés elavult. (C++20 óta)

  • Ha bármelyik operandus scoped enumerációs típusú, nem történik konverzió: a másik operandusnak és a visszatérési típusnak azonos típusúnak kell lennie
  • Egyébként, ha valamelyik operandus long double, a másik operandus átalakításra kerül long double-ra
  • Egyébként, ha valamelyik operandus double, a másik operandus átalakításra kerül double-ra
  • Egyébként, ha valamelyik operandus float, a másik operandus float-tá konvertálódik
  • Egyébként az operandus egész típusú (mivel a bool, char, char8_t, char16_t, char32_t, wchar_t és a nem skopált felsorolás ezen a ponton előléptetésre került), és integrálkonverziókat alkalmazunk a közös típus előállításához, az alábbiak szerint:
  • Ha mindkét operandus előjeles vagy mindkettő előjel nélküli, akkor a kisebb konverziós ranggal rendelkező operandus a nagyobb egészértékű konverziós ranggal rendelkező operandusra konvertálódik
  • Ellenkező esetben, ha az előjel nélküli operandus konverziós rangja nagyobb vagy egyenlő az előjeles operandus konverziós rangjával, akkor az előjeles operandus az előjel nélküli operandus típusára konvertálódik.
  • Egyébként, ha az előjeles operandus típusa az előjel nélküli operandus minden értékét ábrázolni tudja, akkor az előjel nélküli operandus az előjeles operandus típusává konvertálódik
  • Egyébként mindkét operandus az előjeles operandus típusának előjel nélküli megfelelőjévé konvertálódik.

A fenti konverziós rang a bool, signed char, short, int, long, long long sorrendben nő. Bármely előjel nélküli típus rangja megegyezik a megfelelő előjeles típus rangjával. A char rangja megegyezik az signed char és az unsigned char rangjával. A char8_t, char16_t, char32_t és wchar_t rangja megegyezik a mögöttes típusok rangjával.

Túlcsordulás

Az előjel nélküli egész számok aritmetikája mindig modulo 2n
val történik, ahol n az adott egész számban lévő bitek száma. Például az előjel nélküli int esetében, ha az UINT_MAX-hez hozzáadunk egyet, akkor 0-t kapunk, és ha 0-ból kivonunk egyet, akkor UINT_MAX-et kapunk.

Ha az előjeles egész számok aritmetikai művelete túlcsordul (az eredmény nem fér bele az eredménytípusba), a viselkedés nem meghatározott, – az ilyen művelet lehetséges megnyilvánulásai a következők:

  • az ábrázolás szabályai szerint (jellemzően 2-es komplement) körbetekeredik,
  • csapdába esik – egyes platformokon vagy a fordítói opciók miatt (pl.pl. -ftrapv a GCC-ben és a Clangban),
  • minimális vagy maximális értékre telítődik (sok DSP-n),
  • a fordító teljesen optimalizálja ki.

Lebegőpontos környezet

Ha a #pragma STDC FENV_ACCESS támogatott és ON értékre van állítva, minden lebegőpontos aritmetikai operátor az aktuális lebegőpontos kerekítési iránynak engedelmeskedik, és a lebegőpontos aritmetikai hibákat a math_errhandlingben meghatározottak szerint jelenti, kivéve, ha statikus inicializáló része (ebben az esetben a lebegőpontos kivételek nem jelennek meg, és a kerekítési mód a legközelebbi)

Lebegőpontos kontrakció

Hacsak a #pragma STDC FP_CONTRACT támogatott és OFF-re van állítva, minden lebegőpontos aritmetika úgy végezhető, mintha a közbenső eredmények végtelen tartományúak és végtelen pontosságúak lennének, azaz a kerekítési hibákat és a lebegőpontos kivételeket elhagyó optimalizálás megengedett. Például a C++ lehetővé teszi az (x*y) + z megvalósítását egyetlen fuzionált szorzási-addálási CPU-utasítással vagy az a = x*x*x*x*x; optimalizálásával, mint tmp = x *x; a = tmp*tmp.

A szerződéskötéshez nem kapcsolódóan a lebegőpontos aritmetika közbenső eredményeinek tartománya és pontossága eltérhet a típusa által megadottól, lásd FLT_EVAL_METHOD

A C++ szabvány nem vállal garanciát a lebegőpontos műveletek pontosságára.

Unáris aritmetikai operátorok

Az unáris aritmetikai operátorok kifejezései a

+ kifejezés formájúak. (1)
- kifejezés (2)
1) unáris plusz (promóció).
A beépített operátorhoz a kifejezésnek aritmetikai, nem skópolt felsorolás vagy mutató típusúnak kell lennie. Az integrál előléptetés az operanduson történik, ha az integrál vagy nem skópolt felsorolás típusú, és meghatározza az eredmény típusát.
2) unáris mínusz (negáció).
A beépített operátor esetében a kifejezésnek aritmetikai vagy nem skópolt felsorolás típusúnak kell lennie. Az egészértékű előléptetés az operanduson történik, és meghatározza az eredmény típusát.

A beépített unáris plusz operátor az operandusának értékét adja vissza. Az egyetlen helyzet, amikor nem no-op, az, ha az operandus integrál típusú vagy nem skópolt felsorolás típusa, amelyet az integrál előléptetés megváltoztat, pl. char-t int-té alakít, vagy ha az operandus l-értékből r-értékké, tömbből mutatóvá vagy függvényből mutatóvá konvertálásnak van kitéve.

A beépített unáris mínusz operátor az előléptetett operandusának negatívját számítja ki. Előjel nélküli a esetén -a értéke 2b
-a, ahol b a promóció utáni bitek száma.

A felhasználó által definiált operátorokkal szembeni túlterhelésfeloldásban minden A előléptetett aritmetikai típus és minden T típus esetében a következő függvényaláírások vesznek részt:

A operátor+(A)

T* operátor+(T*)

A operátor-(A)

A kód futtatása
#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; std::cout << "size of array: " << sizeof a << '\n' << "size of pointer: " << sizeof +a << '\n';}

Kimenet:

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

Additív operátorok

A bináris additív aritmetikai operátorok kifejezései

lhs + rhs (1)
lhs - rhs (2)
1) összeadás
Az építő-in operátor, lhs és rhs az alábbiak egyikének kell lennie:

  • mindkettő aritmetikai vagy nem skopált felsorolás típusú. Ebben az esetben a szokásos aritmetikai átalakítások mindkét operanduson végrehajtódnak, és meghatározzák az eredmény típusát.
  • az egyik mutató teljesen definiált objektumtípusra, a másik integrál vagy nem skopált felsorolás típus. Ebben az esetben az eredmény típusa a mutató típusa.
2) kivonás
A beépített operátor esetében az lhs és az rhs az alábbiak valamelyikének kell lennie:

  • mindkettő aritmetikai vagy nem skopált felsorolás típusú. Ebben az esetben a szokásos aritmetikai átalakítások mindkét operanduson végrehajtódnak, és meghatározzák az eredmény típusát.
  • lhs egy teljesen definiált objektumtípusra mutató mutató, rhs integrál vagy nem skopált felsorolás típus. Ebben az esetben az eredmény típusa a mutató típusa.
  • mindkettő mutató ugyanarra a teljesen definiált objektumtípusra mutat, a cv-minősítőket figyelmen kívül hagyva. Ebben az esetben az eredmény típusa std::ptrdiff_t.

Az aritmetikai vagy felsorolás típusú operandusok esetén a bináris plusz operátor eredménye az operandusok összege (a szokásos aritmetikai átalakítások után), a bináris mínusz operátor eredménye pedig a második operandusnak az elsőből való kivonásának eredménye (a szokásos aritmetikai átalakítások után), kivéve, hogy ha a típus támogatja az IEEE lebegőpontos aritmetikát (lásd std::numeric_limits::is_iec559),

  • ha az egyik operandus NaN, akkor az eredmény NaN
  • végtelen mínusz végtelen NaN és FE_INVALID emelt
  • végtelen plusz a negatív végtelen NaN és FE_INVALID emelt

Ha valamelyik operandus egy mutató, akkor a következő szabályok érvényesek:

  • A nem tömb objektumra mutató mutatót úgy kell kezelni, mint egy 1 méretű tömb első elemére mutató mutatót.
  • Ha a P mutató egy tömb i. elemére mutat, akkor a P+n, n+P és P-n kifejezések olyan azonos típusú mutatók, amelyek ugyanannak a tömbnek a i+n., i+n. és i-n. elemére mutatnak. A mutatók összeadásának eredménye lehet egy eggyel a végén lévő mutató is (azaz a P mutató olyan, hogy a P-1 kifejezés a tömb utolsó elemére mutat). Minden más helyzet (azaz olyan mutató létrehozására tett kísérlet, amely nem ugyanannak a tömbnek egy elemére mutat, vagy egy, a végén túlmutató mutató) meghatározatlan viselkedést idéz elő.
  • Ha a P mutató egy tömb i. elemére mutat, és a Q mutató ugyanannak a tömbnek a j. elemére mutat, akkor a P-Q kifejezésnek i-j értéke van, ha az érték belefér az std::ptrdiff_t-be. Mindkét operandusnak ugyanannak a tömbnek az elemeire kell mutatnia (vagy a tömb vége után egyel), különben a viselkedés nem definiált. Ha az eredmény nem fér bele az std::ptrdiff_t-be, a viselkedés nem definiált.
  • Minden esetben, ha a mutatott típus eltér a tömbelem típusától, a cv minősítésektől eltekintve minden szinten, ha az elemek maguk is mutatók, a mutató aritmetika viselkedése nem definiált. Különösen a pointer aritmetika pointer to base mutatóval, amely egy származtatott objektumokból álló tömb elemére mutat, nem definiált.
  • Ha egy mutatóhoz hozzáadjuk vagy kivonjuk a 0 értéket, az eredmény a mutató, változatlanul. Ha két mutató ugyanarra az objektumra mutat, vagy mindkettő ugyanannak a tömbnek a végén van eggyel túl, vagy mindkettő null mutató, akkor a kivonás eredménye egyenlő (std::ptrdiff_t)0-val.

Ezek a mutató aritmetikai operátorok lehetővé teszik, hogy a mutatók megfeleljenek a LegacyRandomAccessIterator követelményeinek.

A felhasználó által definiált operátorokkal szembeni túlterhelésfeloldásban a L és R előléptetett aritmetikai típusok minden párja és minden T objektumtípus esetében a következő függvényaláírások vesznek részt:

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*)

ahol LR a szokásos. aritmetikai átalakítások L és R

Futtassuk ezt a kódot
#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 = {'a', 'b', 'c', 'd'}; char* p = &a; std::cout << "Pointer addition examples: " << *p << *(p + 2) << *(2 + p) << *(p - 1) << '\n'; char* p2 = &a; std::cout << "Pointer difference: " << p2 - p << '\n';}

Kimenet:

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

Multiplikatív operátorok

A bináris multiplikatív aritmetikai operátorok kifejezései

alakúak.

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
1) szorzás
A beépített-beépített operátor, lhs és rhs mindkettőnek aritmetikai vagy nem skopált felsorolás típusúnak kell lennie.
2) osztás
A beépített operátorhoz lhs és rhs mindkettőnek aritmetikai vagy nem skópolt felsorolás típusúnak kell lennie.
3) maradék
A beépített operátor esetében lhs és rhs mindkettőnek integrál vagy nem skopált felsorolás típusúnak kell lennie

Mindhárom operátor esetében a szokásos aritmetikai átalakítások mindkét operanduson végrehajtódnak, és meghatározzák az eredmény típusát.

A bináris * operátor az operandusok szorzását végzi (a szokásos aritmetikai átalakítások után), kivéve, hogy a lebegőpontos szorzásnál,

  • egy NaN szorzása bármely számmal NaN-t ad
  • a végtelen szorzása nullával NaN-t ad és FE_INVALID-et ad

A bináris operátor / az első operandus osztja a másodikkal (a szokásos aritmetikai átalakítások után).

Integrális operandusok esetén az algebrai hányadost adja.

A hányadost a végrehajtás által meghatározott irányban kerekíti.

(a C++11-ig)

A hányados nullára csonkolódik (a törtrész elvetésre kerül).

(C++11 óta)

Ha a második operandus nulla, a viselkedés nem meghatározott, kivéve, ha lebegőpontos osztás történik és a típus támogatja az IEEE lebegőpontos aritmetikát (lásd std::numeric_limits::is_iec559), akkor:

  • ha az egyik operandus NaN, akkor az eredmény NaN
  • egy nem nulla szám ±0-val való osztása.0 a helyesen előjelzett végtelent adja, és FE_DIVBYZERO-t kap
  • 0,0 osztása 0,0-val NaN-t ad, és FE_INVALID-et kap

A bináris operátor % az első operandus egész számmal való osztásának maradékát adja (a szokásos aritmetikai átalakítások után; megjegyzendő, hogy az operandus típusoknak integrál típusoknak kell lenniük). Ha a hányados a/b ábrázolható az eredménytípusban, akkor (a/b)*b + a%b == a. Ha a második operandus nulla, a viselkedés nem definiált. Ha az a/b hányados nem ábrázolható az eredménytípusban, akkor mind a a/b, mind a a%b viselkedése meghatározatlan (ez azt jelenti, hogy az INT_MIN%-1 nem definiált a 2-es komplement rendszerekben)

Megjegyzés: A C++11-ig, ha a bináris operátor % egyik vagy mindkét operandusa negatív volt, a maradék előjele implementációfüggő volt, mivel az egész szám osztás kerekítési irányától függött. Az std::div függvény jól definiált viselkedést biztosított ebben az esetben.

Megjegyzés: A lebegőpontos maradékhoz lásd std::remainder és std::fmod.

A felhasználó által definiált operátorokkal szembeni túlterhelésfeloldásban a LA és RA előléptetett aritmetikai típusok minden párja és a LI és RI előléptetett integrál típusok minden párja esetében a következő függvényaláírások vesznek részt:

LRA operator*(LA, RA)

LRA operator/(LA, RA)

LRI operator%(LI, RI)

ahol LRx a szokásos aritmetikai átalakítások a Lx és Rx

Futtassa ezt a kódot
#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';}

Kimenet:

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

A bitenkénti logikai operátorok

A bitenkénti aritmetikai operátorok kifejezései

alakúak.

~ rhs (1)
lhs & rhs (2)
lhs | rhs (3)
lhs ^ rhs (4)
1) bitwise NOT
2) bitwise AND
3) bitwise OR
4) bitwise XOR
Az épített-beépített operátorok esetében, lhs és rhs mindkettőnek integrál vagy nem skopált felsorolás típusúnak kell lennie. A szokásos aritmetikai konverziók mindkét operanduson végrehajtódnak, és meghatározzák az eredmény típusát.

Az operátor~ eredménye az argumentum bitenkénti NOT (egykomplementer) értéke (a promóció után). Az operátor& eredménye az operandusok bitenkénti ÉS értéke (a szokásos aritmetikai átalakítások után). Az operator| eredménye az operandusok bitenkénti VAGY értéke (a szokásos aritmetikai átalakítások után). Az operator^ eredménye az operandusok bitenkénti XOR értéke (a szokásos aritmetikai átalakítások után)

A felhasználó által definiált operátorokkal szembeni túlterhelésfeloldásban a L és R előléptetett integrál típusok minden párja esetében a következő függvényaláírások vesznek részt a túlterhelésfeloldásban:

R operator~(R)

LR operator&(L, R)

LR operátor^(L, R)

LR operátor|(L, R)

ahol LR a szokásos. aritmetikai átalakítások L és R

Futtassuk ezt a kódot
#include <iostream>int main(){ std::cout << std::hex << std::showbase; uint16_t mask = 0x00f0; uint32_t a = 0x12345678; std::cout << "Value: " << a << " mask: " << mask << '\n' << "Setting bits: " << (a | mask) << '\n' << "Clearing bits: " << (a & ~mask) << '\n' << "Selecting bits: " << (a & mask) << '\n';}

Kimenet:

Value: 0x12345678 mask: 0xf0Setting bits: 0x123456f8Clearing bits: 0x12345608Selecting bits: 0x70

A bitenkénti eltolási operátorok

A bitenkénti eltolási operátorok kifejezései a

formájúak.

lhs << rhs (1)
lhs >> rhs (2)
1) lhs balra tolása rhs bitekkel
2) lhs jobbra tolása rhs bitekkel
A beépített-beépített operátorok, lhs és rhs mindkettőnek integrál vagy nem skopált felsorolás típusúnak kell lennie. Az integrál előléptetéseket mindkét operanduson elvégezzük.

A visszatérési típus a bal oldali operandus típusa az integrál előléptetések után.

Előjel nélküli a esetén a a << b értéke az a * 2b
értéke, redukált modulo 2N
, ahol N a visszatérési típusban lévő bitek száma (azaz bitenkénti balra eltolás történik, és a céltípusból eltolt biteket elvetjük).

Az előjeles és nem negatív a esetén, ha a * 2b
a visszatérési típus előjel nélküli változatában ábrázolható, akkor ez az érték előjelesre konvertálva a a << b értéke (ez teszi legálissá az INT_MIN létrehozását 1<<31-ként); egyébként a viselkedés nem definiált.

Negatív a esetén a a << b viselkedése nem definiált.

Előjel nélküli a és előjeles és nem negatív a esetén a a >> b értéke az a/2b
egész szám része.

Negatív a esetén a a >> b értéke implementációfüggő (a legtöbb implementációban ez aritmetikai jobbra tolást végez, így az eredmény negatív marad).

(C++20-ig)

A a << b értéke az a * 2b
modulo 2N
val kongruens egyedi érték, ahol N a visszatérési típus bitjeinek száma (azaz bitenkénti balra eltolás történik, és a céltípusból eltolt biteket elvetjük).

A a >> b értéke a/2b
, lefelé kerekítve (más szóval az előjeles a jobbra tolása aritmetikai jobbra tolást jelent).

(C++20 óta)

Minden esetben, ha a jobb oldali operandus értéke negatív vagy nagyobb vagy egyenlő, mint az előléptetett bal oldali operandus bitjeinek száma, a viselkedés nem meghatározott.

A felhasználó által definiált operátorokkal szembeni túlterhelésfeloldásban a L és R előléptetett integrál típusok minden egyes párja esetében a következő függvényaláírások vesznek részt:

L operátor<<(L, R)

L operátor>>(L, R)

A kód futtatása
#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' // overflow in unsigned << "0x10 << 10 = " << (c << 10) << '\n'; // char is promoted to int long long ll = -1000; std::cout << std::dec << "-1000 >> 1 = " << (ll >> ONE) << '\n';}

Kimenet:

0x123 << 1 = 0x2460x123 << 63 = 0x80000000000000000x10 << 10 = 0x4000-1000 >> 1 = -500

Standard könyvtár

Az aritmetikai operátorok számos standard könyvtári típus esetében túlterheltek.

Unáris aritmetikai operátorok

megvalósítja az unáris + és unáris – operátorokat.
(public member function of std::chrono::duration<Rep,Period>)

unáris operátorokat alkalmaz komplex számokra
(function template)

egy unáris aritmetikai operátort alkalmaz a valarray minden elemére
(public member function of std::valarray<T>)

. Additív operátorok

összeadási és kivonási műveleteket végez egy időponttal
(függvénysablon)

aritmetikai műveleteket hajt végre időtartamokkal mint argumentumokkal
(függvénysablon)

összead vagy kivon year_month_day és néhány évek vagy hónapok számát
(public member function of std::chrono::year_month_day)

összefűz két stringet vagy egy stringet és egy char-t
(function template)

előretolja vagy lecsökkenti az iterátort
(public member function of std::reverse_iterator<Iter>)

. továbbítja vagy csökkenti az iterátort
(public member function of std::move_iterator<Iter>)

komplex szám aritmetikát végez két komplex értéken vagy egy komplexen és egy skaláron
(function template)

bináris operátorokat alkalmaz két értéktábla minden elemére, vagy egy valarray és egy érték
(függvénysablon)

Multiplikatív operátorok

aritmetikai műveleteket hajt végre időtartamokkal mint argumentumokkal
(függvénysablon)

komplex számok aritmetikáját hajtja végre két komplex értéken vagy egy komplexen és egy skaláron
(függvénysablon)

bináris operátorokat alkalmaz két értéktábla minden elemére, vagy egy valarray és egy érték
(függvénysablon)

Bitwise logikai operátorok

bináris AND, OR műveleteket hajt végre, XOR és NOT
(public member function of std::bitset<N>)

bináris logikai műveleteket hajt végre bitsorozatokon
(function template)

egy unáris aritmetikai operátort alkalmaz a valarray minden elemére
(public member function of std::valarray<T>)

bináris operátorokat alkalmaz két valarray minden elemére, vagy egy valarray és egy érték
(függvénysablon)

Bitenkénti eltolási operátorok

bináris operátorokat alkalmaz két valarray minden elemére, vagy egy valarray és egy érték
(függvénysablon)

bináris balra és jobbra eltolás
(public member function of std::bitset<N>)

Stream insertion/extraction operators

A standard könyvtárban a bitwise shift operátorok általában I/O stream (std::ios_base& vagy a belőle származtatott osztályok egyike), mint bal oldali operandus és visszatérési típus. Az ilyen operátorokat stream beszúró és stream kivonó operátoroknak nevezzük:

formázott adatok kivonása
(public member function of std::basic_istream<CharT,Traits>)

karakterek és karaktertömbök kivonása
(function template)

formázott adatok beszúrása
(public member function of std::basic_ostream<CharT,Traits>)

karakteradatok beszúrása
(function template)

komplex számot szerializál és deszerializál
(függvénysablon)

bitsorozatok folyam be- és kimenetét végzi
(függvénysablon)

folyam be- és kimenetet végez stringeken
(függvénysablon)

folyam be- és kimenetet végez pszeudo-random number engine
(function template)

performs stream input and output on pseudo-random number distribution
(function template)

Defect reports

A következő, a viselkedést megváltoztató hibajelentéseket visszamenőleg alkalmazták a korábban közzétett C++ szabványokra.

DR Applied to Behavior as published Correct behavior
CWG 1457 C++98 egy pozitív előjelű érték bal szélső 1 bitjének az előjelbitbe való eltolása UB well- lett.definiált

Lásd még

Operator precedence

Operator overloading

Common operators
assignment . inkrementálás
dekrementálás
aritmetikai logikai összehasonlítás tag
hozzáférés
egyéb

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—

+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
? :

Speciális operátorok

static_cast egy típust egy másik kapcsolódó típusba konvertál
dynamic_cast az öröklési hierarchiákon belül konvertál
const_cast cv minősítőket ad vagy vesz el
reinterpret_cast típust nem kapcsolódó típusba konvertál
C-style cast egy típust egy másikba konvertál static_cast keverékével, const_cast és reinterpret_cast
new dinamikus tárolási időtartamú objektumokat hoz létre
delete megsemmisíti a new kifejezéssel korábban létrehozott objektumokat és felszabadítja a kapott memóriaterületet
sizeof lekérdezi egy típus méretét
sizeof… lekérdezi egy paramétercsomag méretét (C++11 óta)
typeid lekérdezi egy típus típusinformációit
noexcept ellenőrzi, hogy egy kifejezés kivételt dobhat-e (C++11 óta)
alignof lekérdezi egy típus igazítási követelményeit (C++11 óta)

C dokumentáció az aritmetikai operátorok számára

Szólj hozzá!