Aritmetické operátory

Jazyk C++

Obecná témata
Řízení toku
Podmíněné. provádění příkazů

if

Iterační příkazy (cykly)

for

rozsah-for (C++11)

Příkazy skoku

continuebreak

goto -. return

Funkce
Deklarace funkce
Deklarace lambda funkce
inline Specifikátor
Specifikace výjimky (do C++20)
. noexcept specifikátor (C++11)
Výjimky
Prostory jmen
Typy
Specifikátory

decltype (C++11)

auto (C++11)

alignas (C++11)

const/volatile

constexpr (C++11)

Specifikátory trvání ukládání
Inicializace
Výrazy
Alternativní reprezentace
Literály
Logické -. Integer – Floating-point
Character – String – nullptr (C++11)
User-definované (C++11)
Nástroje
Atributy (C++11)
Typy
typedef deklarace
Deklarace aliasů typů (C++11)
Casts
Implicitní konverze -. Explicitní konverze
static_castdynamic_cast
const_cast -. reinterpret_cast
Alokace paměti
Třídy
Třídy-specifické vlastnosti funkce

Virtuální funkce

specifikátor override (C++11)

specifikátor final (C++11)

explicit (C++11)

static

Speciální členské funkce

Přiřazení kopie

Přiřazení přesunu (C++11)

Destruktor

Šablony

Specializace šablony

Balíky parametrů (C++11)

Různé
Výrazy

Obecné

kategorie hodnot (lvalue, rvalue, xvalue)

pořadí vyhodnocení (body posloupnosti)

konstantní výrazy

nevyhodnocené výrazy

primární výrazy

lambda-výraz(C++11)

literály

celočíselné literály

plovoucí-bodové literály

logické literály

znakové literály včetně escape sekvencí

řetězcové literály

literál nulového ukazatele(C++11)

uživatelsky definovaný literál(C++11)

Operátory

Operátory přiřazení: a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b

Inkrementace a dekrementace: ++a, --a, a++, a--

Aritmetické operátory:+a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b

Logické operátory: a||b, a&&b, !a

Porovnávací operátory: a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)

Operátory členského přístupu: a, *a, &a, a->b, a.b, a->*b, a.*b

Ostatní operátory: a(...), a,b, a?b:c

new-výraz

delete-výraz

throw-výraz

alignof

sizeof

sizeof…(C++11)

typeid

noexcept(C++11)

Fold expression(C++17)

Alternativní reprezentace operátorů

Precedence a asociativita

Přetěžování operátorů

. Výchozí porovnání(C++20)

Konverze

Implicitní konverze

const_cast

static_cast

reinterpret_cast

dynamic_cast

Explicitní konverze (T)a, T(a)

Uživatelsky definovaná konverze

Vrací výsledek konkrétní aritmetické operace.

.

Název operátoru Syntaxe Přetížitelný Příklady prototypů (pro třídu T)
Uvnitř definice třídy Mimo definici třídy
unární plus +a Ano T::operator+() const; T operator+(const T &a);
unární minus -a Ano 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);
odčítání a - b Ano T T::operator-(const T2 &b) const; T operator-(const T &a, const T2 &b);
násobení a * b Ano T T::operator*(const T2 &b) const; T operator*(const T &a, const T2 &b);
dělení a / b Ano T T::operator/(const T2 &b) const; T operator/(const T &a, const T2 &b);
modulo a % b Ano 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);
Poznámky

  • Všechny vestavěné operátory vracejí hodnoty a většina uživatelsky definovaných přetížení také vrací hodnoty, takže uživatelsky definované operátory lze používat stejným způsobem jako vestavěné. V uživatelsky definovaném přetížení operátoru však lze jako návratový typ použít libovolný typ (včetně void). Konkrétně přetížení operator<< a operator>> pro vkládání a odebírání proudu vrací T&.
  • T2 může být libovolný typ včetně T

  • 1 Vysvětlivky
    • 1.1 Převody
    • 1.2 Přetečení
    • 1.3 Prostředí plovoucí řádové čárky
    • 1.4 Kontrakce plovoucí řádové čárky
    • 1.5 Unární aritmetické operátory
    • 1.6 Aditivní operátory
    • 1.7 Multiplikativní operátory
    • 1.8 Bitové logické operátory
    • 1.9 Operátory bitového posunu
  • 2 Standardní knihovna
    • 2.1 Unární aritmetické operátory
    • 2.2 Aditivní operátory
    • 2.3 Multiplikativní operátory
    • 2.4 Operátory bitové logiky
    • 2.5 Operátory bitového posunu
    • 2.6 Operátory vkládání/vyjímání proudu
  • 3 Hlášení závad
  • 4 Viz také

Vysvětlení

Všechny aritmetické operátory počítají výsledek konkrétní aritmetické operace a vrací její výsledek. Argumenty se nemění.

Převody

Je-li operand předávaný aritmetickému operátoru integrální nebo neskopírovaný výčtový typ, pak před jakoukoli další akcí (ale po případném převodu z lhodnoty na rhodnotu) projde operand integrální propagací. Pokud má operand typ pole nebo funkce, použijí se konverze pole na ukazatel a funkce na ukazatel.

U binárních operátorů (kromě posunů), pokud mají povyšované operandy různé typy, se použije další sada implicitních konverzí, známých jako obvyklé aritmetické konverze s cílem vytvořit společný typ (přístupný také prostřednictvím typové vlastnosti std::common_type). Pokud je před jakoukoli integrální propagací jeden operand výčtového typu a druhý operand je typu s pohyblivou řádovou čárkou nebo jiného výčtového typu, je toto chování zastaralé. (od C++20)

  • Pokud má některý z operandů rozsah výčtového typu, konverze se neprovádí: druhý operand a návratový typ musí mít stejný typ
  • Jinak, pokud je některý z operandů long double, druhý operand se převede na long double
  • Jinak, pokud je některý z operandů double, druhý operand se převede na double
  • Jinak, pokud je některý z operandů float, druhý operand se převede na float
  • V opačném případě má operand celočíselný typ (protože v tomto bodě byly povýšeny bool, char, char8_t, char16_t, char32_t, wchar_t a neskopírovaný výčet) a pro vytvoření společného typu se použijí integrální konverze, jak je uvedeno níže:
  • Pokud jsou oba operandy podepsané nebo oba nepodepsané, převede se operand s menší konverzní hodností na operand s větší celočíselnou konverzní hodností
  • V opačném případě, pokud je konverzní hodnost nepodepsaného operandu větší nebo rovna konverzní hodnosti podepsaného operandu, převede se podepsaný operand na typ nepodepsaného operandu.
  • V opačném případě, pokud typ signed operandu může reprezentovat všechny hodnoty unsigned operandu, je unsigned operand převeden na typ signed operandu

  • V opačném případě jsou oba operandy převedeny na unsigned protějšek typu signed operandu.

Výše uvedená konverzní hodnost se zvyšuje v pořadí bool, signed char, short, int, long, long long. Hodnost libovolného nepodepsaného typu je rovna hodnosti odpovídajícího podepsaného typu. Hodnost char je rovna hodnosti signed char a unsigned char. Hodnosti typů char8_t, char16_t, char32_t a wchar_t jsou rovny hodnostem jejich základních typů.

Přetečení

Aritmetika celých čísel bez znaménka se vždy provádí modulo 2n
kde n je počet bitů v daném celém čísle. Např. pro unsigned int přičtením jedničky k UINT_MAX získáme 0 a odečtením jedničky od 0 získáme UINT_MAX.

Pokud aritmetická operace se znaménkem celého čísla přeteče (výsledek se nevejde do typu výsledku), je chování nedefinované, – mezi možné projevy takové operace patří:

  • obalí se podle pravidel reprezentace (typicky doplněk 2),
  • zachytí se – na některých platformách nebo kvůli volbám kompilátoru (např.např. -ftrapv v GCC a Clangu),
  • nasytí se na minimální nebo maximální hodnotu (na mnoha DSP),
  • je kompilátorem zcela optimalizován.

Prostředí s plovoucí desetinnou čárkou

Pokud je podporováno #pragma STDC FENV_ACCESS a je nastaveno na ON, všechny aritmetické operátory s pohyblivou řádovou čárkou se řídí aktuálním směrem zaokrouhlování a hlásí chyby aritmetiky s pohyblivou řádovou čárkou, jak je uvedeno v math_errhandling, pokud nejsou součástí statického inicializátoru (v takovém případě nejsou vyvolány výjimky s pohyblivou řádovou čárkou a režim zaokrouhlování je na nejbližší)

Kontrakce s pohyblivou řádovou čárkou

Pokud není podporováno #pragma STDC FP_CONTRACT a nastaveno na OFF, lze veškerou aritmetiku s pohyblivou řádovou čárkou provádět, jako by mezivýsledky měly nekonečný rozsah a přesnost, tj. jsou povoleny optimalizace, které vynechávají chyby zaokrouhlování a výjimky s pohyblivou řádovou čárkou. Například jazyk C++ umožňuje implementovat (x*y) + z pomocí jediné instrukce CPU fused multiply-add nebo optimalizaci a = x*x*x*x; jako tmp = x *x; a = tmp*tmp.

S kontrakcí nesouvisí, že mezivýsledky aritmetiky s pohyblivou řádovou čárkou mohou mít rozsah a přesnost odlišnou od té, která je uvedena u jejich typu, viz FLT_EVAL_METHOD

Formálně standard C++ neposkytuje žádnou záruku přesnosti operací s pohyblivou řádovou čárkou.

Unární aritmetické operátory

Výrazy unárních aritmetických operátorů mají tvar

+ výraz . (1)
- výraz (2)
1) unární plus (povýšení).
Pro vestavěný operátor musí mít výraz aritmetický, neskopírovaný výčtový nebo ukazatelový typ. Integrální povýšení se provádí na operandu, pokud má integrální nebo neskopovaný výčtový typ, a určuje typ výsledku.

2) unární minus (negace).
Pro vestavěný operátor musí mít výraz aritmetický nebo neskopovaný výčtový typ. Integrální povýšení se provádí na operandu a určuje typ výsledku.

Vestavěný operátor unární plus vrací hodnotu svého operandu. Jedinou situací, kdy se nejedná o no-op, je situace, kdy má operand integrální typ nebo neskopovaný výčtový typ, který se mění integrální propagací, např. převádí char na int nebo pokud je operand předmětem konverze lvalue-to-rvalue, array-to-pointer nebo function-to-pointer.

Vestavěný unární operátor minus vypočítá zápornou hodnotu svého propagovaného operandu. Pro unsigned a je hodnota -a 2b
-a, kde b je počet bitů po povýšení.

Při řešení přetížení proti uživatelsky definovaným operátorům se pro každý povýšený aritmetický typ A a pro každý typ T účastní řešení přetížení následující signatury funkcí:

A operator+(A)

T* operator+(T*)

A operator-(A)

Spustit tento kód
#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';}

Výstup:

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

Aditivní operátory

Výrazy binárních aditivních aritmetických operátorů mají tvar

lhs + rhs (1)
lhs - rhs (2)
1) sčítání
Pro postavené-vestavěný operátor, lhs a rhs musí být jedna z následujících hodnot:

  • oba mají aritmetický nebo neskopírovaný výčtový typ. V tomto případě se provedou obvyklé aritmetické konverze na oba operandy a určí se typ výsledku.
  • jeden je ukazatel na zcela definovaný typ objektu, druhý má integrální nebo neskopovaný výčtový typ. V tomto případě má typ výsledku typ ukazatele.
2) odčítání
U vestavěného operátoru musí být lhs a rhs jeden z následujících typů:

  • oba mají aritmetický nebo neskopovaný výčtový typ. V tomto případě se provedou obvyklé aritmetické konverze na oba operandy a určí typ výsledku.
  • lhs je ukazatel na zcela definovaný typ objektu, rhs má integrální nebo neskopovaný výčtový typ. V tomto případě má typ výsledku typ ukazatele.
  • oba jsou ukazatele na stejné zcela definované objektové typy, přičemž se ignorují cv-kvalifikátory. V tomto případě je výsledný typ std::ptrdiff_t.

Při operandech aritmetického nebo výčtového typu je výsledkem binárního operátoru plus součet operandů (po obvyklých aritmetických převodech) a výsledkem binárního operátoru minus je výsledek odečtení druhého operandu od prvního (po obvyklých aritmetických převodech) s tím, že pokud typ podporuje aritmetiku IEEE s pohyblivou řádovou čárkou (viz std::numeric_limits::is_iec559),

  • pokud je jeden operand NaN, výsledkem je NaN
  • nekonečno minus nekonečno je NaN a FE_INVALID je zvýšeno
  • nekonečno plus záporné nekonečno je NaN a FE_INVALID je zvýšeno

Pokud je některý z operandů ukazatel, platí následující pravidla:

  • Ukazatel na objekt, který není polem, se považuje za ukazatel na první prvek pole o velikosti 1.
  • Pokud ukazatel P ukazuje na itý prvek pole, pak výrazy P+n, n+P a P-n jsou ukazatele stejného typu, které ukazují na i+ntý, i+ntý a i-ntý prvek téhož pole. Výsledkem sčítání ukazatelů může být také ukazatel s jedním koncem (tj. ukazatel P takový, že výraz P-1 ukazuje na poslední prvek pole). Jakékoli jiné situace (tj. pokusy o generování ukazatele, který neukazuje na prvek téhož pole nebo na prvek za koncem) vyvolávají nedefinované chování.
  • Pokud ukazatel P ukazuje na itý prvek pole a ukazatel Q ukazuje na jtý prvek téhož pole, má výraz P-Q hodnotu i-j, pokud se tato hodnota vejde do std::ptrdiff_t. Oba operandy musí ukazovat na prvky téhož pole (nebo na jeden za koncem), jinak je chování nedefinované. Pokud se výsledek nevejde do std::ptrdiff_t, je chování nedefinované.
  • V každém případě, pokud se typ ukazatele liší od typu prvku pole, bez ohledu na cv kvalifikace, na každé úrovni, pokud jsou prvky samy ukazateli, je chování aritmetiky ukazatelů nedefinované. Zejména aritmetika ukazatele s ukazatelem na bázi, který ukazuje na prvek pole odvozených objektů, je nedefinovaná.
  • Pokud se k ukazateli přičte nebo odečte hodnota 0, výsledkem je ukazatel beze změny. Pokud dva ukazatele ukazují na stejný objekt nebo jsou oba jeden za koncem stejného pole, případně jsou oba nulové, pak je výsledek odečtení roven (std::ptrdiff_t)0.

Tyto operátory aritmetiky ukazatelů umožňují, aby ukazatele splňovaly požadavky LegacyRandomAccessIterator.

Při řešení přetížení proti uživatelsky definovaným operátorům se pro každou dvojici povýšených aritmetických typů L a R a pro každý objektový typ T účastní řešení přetížení následující signatury funkcí:

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

kde LR je výsledek obvyklého postupu. aritmetických převodů na L a R

Spustit tento kód
#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';}

Výstup:

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

Multiplikativní operátory

Výrazy binárních multiplikativních aritmetických operátorů mají tvar

.

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
1) násobení
Pro vestavěné-vestavěný operátor, lhs a rhs musí mít oba aritmetický nebo neskopovaný výčtový typ.
2) dělení
Pro vestavěný operátor musí mít lhs i rhs aritmetický nebo neskopovaný výčtový typ.
3) zbytek
U vestavěného operátoru musí mít lhs i rhs integrální nebo neskopovaný výčtový typ

U všech tří operátorů se provádějí obvyklé aritmetické konverze na oba operandy a určují typ výsledku.

Binární operátor * provádí násobení svých operandů (po obvyklých aritmetických konverzích) s tím, že pro násobení s plovoucí desetinnou čárkou,

  • násobení NaN libovolným číslem dává NaN
  • násobení nekonečna nulou dává NaN a je vyvoláno FE_INVALID

Binární operátor / dělí první operand druhým (po obvyklých aritmetických převodech).

Pro integrální operandy dává algebraický kvocient.

Kvocient je zaokrouhlen v implementací definovaném směru.

(do C++11)

Kvócient se zkrátí směrem k nule (zlomková část se zahodí).

(od C++11)

Pokud je druhý operand nula, je chování nedefinované, s výjimkou toho, že pokud probíhá dělení s plovoucí desetinnou čárkou a typ podporuje aritmetiku IEEE s plovoucí desetinnou čárkou (viz std::numeric_limits::is_iec559), pak:

  • pokud je jeden operand NaN, výsledkem je NaN
  • dělení nenulového čísla číslem ±0.0 dává správně podepsané nekonečno a je vyvoláno FE_DIVBYZERO
  • dělení 0,0 číslem 0,0 dává NaN a je vyvoláno FE_INVALID

Binární operátor % dává zbytek celočíselného dělení prvního operandu druhým (po obvyklých aritmetických převodech; všimněte si, že typy operandů musí být integrální typy). Pokud je kvocient a/b reprezentovatelný ve výsledném typu, (a/b)*b + a%b == a. Pokud je druhý operand nula, je chování nedefinované. Pokud kvocient a/b není reprezentovatelný ve výsledném typu, je chování a/b i a%b nedefinované (to znamená, že INT_MIN%-1 je nedefinovaný na systémech s dvojkovým doplňkem)

Poznámka: Do C++11, pokud byl jeden nebo oba operandy binárního operátoru % záporné, bylo znaménko zbytku implementačně definované, protože záviselo na směru zaokrouhlování celočíselného dělení. Funkce std::div poskytovala v tomto případě dobře definované chování.

Poznámka: Pro zbytek v plovoucí řádové čárce viz std::remainder a std::fmod.

Při řešení přetížení proti uživatelsky definovaným operátorům se pro každou dvojici povýšených aritmetických typů LA a RA a pro každou dvojici povýšených integrálních typů LI a RI účastní řešení přetížení následující signatury funkcí:

LRA operator*(LA, RA)

LRA operator/(LA, RA)

LRI operator%(LI, RI)

kde LRx je výsledek běžného aritmetických převodů na Lx a Rx

Spustit tento kód
#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';}

Výstup:

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

Bitové logické operátory

Výrazy bitových aritmetických operátorů mají tvar

.

~ rhs (1)
lhs & rhs (2)
lhs | rhs (3)
lhs ^ rhs (4)
1) bitový NOT
2) bitový AND
3) bitový OR
4) bitový XOR
Pro vestavěné-vestavěných operátorů, lhs a rhs musí mít oba integrální nebo neskopírovaný výčtový typ. Obvyklé aritmetické konverze se provádějí na obou operandech a určují typ výsledku.

Výsledkem operátoru~ je hodnota bitového NOT (jedničkového doplňku) argumentu (po povýšení). Výsledkem operátoru& je bitová hodnota AND operandů (po obvyklých aritmetických převodech). Výsledkem operátoru| je bitová hodnota OR operandů (po obvyklých aritmetických převodech). Výsledkem operátoru^ je bitová hodnota XOR operandů (po obvyklých aritmetických převodech)

Při řešení přetížení proti uživatelsky definovaným operátorům se pro každou dvojici povýšených integrálních typů L a R účastní řešení přetížení následující signatury funkcí:

R operator~(R)

LR operator&(L, R)

LR operátor^(L, R)

LR operátor|(L, R)

kde LR je výsledek obvyklého. aritmetických převodů na L a R

Spustit tento kód
#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';}

Výstup:

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

Operátory bitového posunu

Výrazy operátorů bitového posunu mají tvar

.

lhs << rhs (1)
lhs >> rhs (2)
1) levý posun lhs o rhs bity
2) pravý posun lhs o rhs bity
Pro vestavbu-vestavěných operátorů, lhs a rhs musí mít oba integrální nebo neskopírovaný výčtový typ. Integrální povýšení se provádí na obou operandech.

Vratný typ je typ levého operandu po integrálním povýšení.

Pro unsigned a je hodnota a << b hodnotou a * 2b
, redukovanou modulo 2N
kde N je počet bitů v návratovém typu (tj. provede se bitový posun doleva a bity, které se posunou mimo cílový typ, se zahodí).

Pro znaménkové a nezáporné a, pokud je * 2b
reprezentovatelné v nezáporné verzi návratového typu, pak je tato hodnota převedená na znaménkovou hodnotou a << b (díky tomu je legální vytvořit INT_MIN jako 1<<31); jinak je chování nedefinované.

Pro záporné a je chování a << b nedefinované.

Pro nepodepsaný a a pro podepsaný a nezáporný a je hodnota a >> b celočíselnou částí a/2b
.

Pro záporný a je hodnota a >> b implementačně definovaná (ve většině implementací se tím provádí aritmetický posun doprava, takže výsledek zůstává záporný).

(do C++20)

Hodnota a << b je jedinečná hodnota shodná s a * 2b
modulo 2N
kde N je počet bitů v návratovém typu (tj. provede se bitový posun doleva a bity, které se posunou mimo cílový typ, se zahodí).

Hodnota a >> b je a/2b
, zaokrouhlená dolů (jinými slovy, posun doprava na signed a je aritmetický posun doprava).

(od C++20)

V každém případě, pokud je hodnota pravého operandu záporná nebo je větší nebo rovna počtu bitů v povýšeném levém operandu, je chování nedefinované.

Při řešení přetížení proti uživatelsky definovaným operátorům se pro každou dvojici povýšených integrálních typů L a R účastní řešení přetížení následující signatury funkcí:

L operator<<(L, R)

L operator>>(L, R)

Spustit tento kód
#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';}

Výstup:

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

Standardní knihovna

Aritmetické operátory jsou přetíženy pro mnoho typů standardní knihovny.

Unární aritmetické operátory

implementuje unární + a unární -.
(veřejná členská funkce std::chrono::duration<Rep,Period>)

aplikuje unární operátory na komplexní čísla
(šablona funkce)

aplikuje unární aritmetický operátor na každý prvek pole valarray
(veřejná členská funkce std::valarray<T>)

Aditivní operátory

provádí operace sčítání a odčítání zahrnující časový bod
(šablona funkce)

implementuje aritmetické operace s dobou trvání jako argumentem
(šablona funkce)

sčítá nebo odčítá year_month_day a nějaké počet let nebo měsíců
(veřejná členská funkce std::chrono::year_month_day)

spojí dva řetězce nebo řetězec a znak
(šablona funkce)

posune nebo sníží iterátor
(veřejná členská funkce std::reverse_iterator<Iter>)

posunuje nebo dekrementuje iterátor
(veřejná členská funkce std::move_iterator<Iter>)

provádí aritmetiku komplexních čísel na dvou komplexních hodnotách nebo komplexu a skaláru
(šablona funkce)

aplikuje binární operátory na každý prvek dvou valarů, nebo valarray a hodnotu
(šablona funkce)

Multiplikativní operátory

provádí aritmetické operace s délkami trvání jako argumenty
(šablona funkce)

provádí aritmetiku komplexních čísel nad dvěma komplexními hodnotami nebo komplexem a skalárem
(šablona funkce)

aplikuje binární operátory na každý prvek dvou valarů, nebo valarray a hodnotu
(šablona funkce)

Bitové logické operátory

provádí binární AND, OR, XOR a NOT
(veřejná členská funkce std::bitset<N>)

provádí binární logické operace nad bitovými množinami
(šablona funkce)

aplikuje unární aritmetický operátor na každý prvek valarray
(veřejná členská funkce std::valarray<T>)

aplikuje binární operátory na každý prvek dvou valarray, nebo valarray a hodnota
(šablona funkce)

Operátory bitového posunu

aplikuje binární operátory na každý prvek dvou valarray, nebo valarray a hodnotu
(šablona funkce)

provádí binární posun doleva a posun doprava
(veřejná členská funkce std::bitset<N>)

Operátory vkládání/vyjímání proudu

Ve standardní knihovně jsou operátory bitového posunu běžně přetěžovány pomocí I/O proudu (std::ios_base& nebo některou z odvozených tříd) jako levý operand i návratový typ. Takové operátory jsou známé jako operátory vkládání a vyjímání proudu:

vytahuje formátovaná data
(veřejná členská funkce std::basic_istream<CharT,Traits>)

vytahuje znaky a znaková pole
(šablona funkce)

vkládá formátovaná data
(veřejná členská funkce std::basic_ostream<CharT,Traits>)

vkládá znaková data
(šablona funkce)

serializuje a deserializuje komplexní číslo
(šablona funkce)

provádí proudový vstup a výstup bitových množin
(šablona funkce)

provádí proudový vstup a výstup na řetězcích
(šablona funkce)

provádí proudový vstup a výstup na pseudo-náhodných čísel
(šablona funkce)

provádí proudový vstup a výstup na pseudonáhodném rozdělení čísel
(šablona funkce)

Hlášení o závadách

Následující hlášení o závadách měnících chování byla použita zpětně na dříve vydané normy C++.

DR Aplikováno na Chování ve zveřejněné podobě Správné chování
CWG 1457 C++98 posunutí krajního levého 1 bitu kladné znaménkové hodnoty do znaménkového bitu bylo UB provedeno dobře.definován

Viz také

Přednost operátorů

Přetěžování operátorů

Společné operátory
přiřazení inkrementace
dekrementace
aritmetické logické porovnávací členské
přístupové
jiné

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

Speciální operátory

static_cast převádí jeden typ na jiný příbuzný typ
dynamic_cast převádí v rámci hierarchie dědičnosti
const_cast přidává nebo odebírá kvalifikátory cv
reinterpret_cast převádí typ na nepříbuzný typ
C-style cast převádí jeden typ na jiný pomocí směsi static_cast, const_cast a reinterpret_cast
new vytvoří objekty s dynamickým trváním paměti
delete zničí objekty dříve vytvořené výrazem new a uvolní získanou oblast paměti
sizeof se dotazuje na velikost typu
sizeof…. se dotazuje na velikost paketu parametrů (od C++11)
typeid se dotazuje na informace o typu typu
noexcept kontroluje, zda výraz může vyhodit výjimku (od C++11)
alignof se dotazuje na požadavky na zarovnání typu (od C++11)

Dokumentace jazyka C pro aritmetické operátory

.

Napsat komentář