Operátory v C a C++

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 13. září 2022; ověření vyžaduje 1 úpravu .

Programovací jazyk C++ podporuje všechny operátory svého předchůdce C a je vylepšen o nové operátory a funkce.

Po vyhodnocení prvního operandu pro nepřetížené operátory " && ", " || ” a “ , ” (operátor “čárka”, angl.  čárka ) kompilátor vloží sekvenční bod ( angl.  sekvenční bod ), který zaručí, že budou provedeny všechny vedlejší efekty (například operátor “postfix ++”). před vyhodnocením druhého operandu.

Jazyky se syntaxí podobnou C (jako je Java , C# , PHP a další) si často vypůjčují operátory C/C++, přičemž zachovávají nejen jejich chování, ale také přednost a asociativitu .

Tabulky

Tabulky používají následující zápis:

struct T { // nebo operátor třídy float () const ; }; T :: operátor float () const { /* implementace */ };
  • "Definice mimo třídu": definování operátoru jako funkce; příklad:
#include <iostream> struct T { // nebo class /* ... */ }; std :: ostream & operátor << ( std :: ostream & a , T const & b ) { /* implementace */ }
  • "N/A" : Není k dispozici .

Aritmetické operátory

Operace (výraz) Operátor Syntaxe výrazu Přetížitelné Implementováno v C Příklad
Člen typu T Definice mimo třídu
Úkol = a = b Ano Ano R& T::operator =(S b); n/a
Přidání + a + b Ano Ano R T::operator +(S b); R operator +(T a, S b);
Odčítání - a - b Ano Ano R T::operator -(S b); R operator -(T a, S b);
unární plus + +a Ano Ano R T::operator +(); R operator +(T a);
unární mínus - -a Ano Ano R T::operator -(); R operator -(T a);
Násobení * a * b Ano Ano R T::operator *(S b); R operator *(T a, S b);
Divize / a / b Ano Ano R T::operator /(S b); R operator /(T a, S b);
Operační modul ( zbytek z dělení celých čísel) [poznámka 1] % a % b Ano Ano R T::operator %(S b); R operator %(T a, S b);
Přírůstek předpona ++ ++a Ano Ano R& T::operator ++(); R& operator ++(T a);
přípona (postfix) ++ a++ Ano Ano R T::operator ++(int); R operator ++(T a, int);
[poznámka 2]
Dekrementovat předpona -- --a Ano Ano R& T::operator --(); R& operator --(T a);
přípona (postfix) -- a-- Ano Ano R T::operator --(int); R operator --(T a, int);
[poznámka 2]

Porovnávací operátory

Operace (výraz) Operátor Syntaxe výrazu Přetížitelné Implementováno v C Příklad
Člen typu T Definice mimo třídu
Rovnost == a == b Ano Ano R T::operator ==(S b); R operator ==(T a, S b);
Nerovnost != a != b Ano Ano R T::operator !=(S b); R operator !=(T a, S b);
Více > a > b Ano Ano R T::operator >(S b); R operator >(T a, S b);
Méně < a < b Ano Ano R T::operator <(S b); R operator <(T a, S b);
Více nebo stejné >= a >= b Ano Ano R T::operator >=(S b); R operator >=(T a, S b);
Méně nebo stejně <= a <= b Ano Ano R T::operator <=(S b); R operator <=(T a, S b);

Logické operátory

Operace (výraz) Operátor Syntaxe výrazu Přetížitelné Implementováno v C Příklad
Člen typu T Definice mimo třídu
Logická negace, NE ! !a Ano Ano R T::operator !(); R operator !(T a);
Booleovské násobení, AND && a && b Ano Ano R T::operator &&(S b); R operator &&(T a, S b);
Logické sčítání, NEBO || a || b Ano Ano R T::operator ||(S b); R operator ||(T a, S b);

Bitové operátory

Operace (výraz) Operátor Syntaxe výrazu Přetížitelné Implementováno v C Příklad
Člen typu T Definice mimo třídu
bitová inverze ~ ~a Ano Ano R T::operator ~(); R operator ~(T a);
Bitové AND & a & b Ano Ano R T::operator &(S b); R operator &(T a, S b);
Bitové NEBO (nebo) | a | b Ano Ano R T::operator |(S b); R operator |(T a, S b);
Bitové XOR (xor) ^ a ^ b Ano Ano R T::operator ^(S b); R operator ^(T a, S b);
Bitový levý Shift [poznámka 3] << a << b Ano Ano R T::operator <<(S b); R operator <<(T a, S b);
Bitový posun vpravo [poznámka 3] [poznámka 4] >> a >> b Ano Ano R T::operator >>(S b); R operator >>(T a, S b);

Složené zadání

Operace (výraz) Operátor Syntaxe výrazu Význam Přetížitelné Implementováno v C Příklad
Člen typu T Definice mimo třídu
Sčítání v kombinaci se zadáním += a += b a = a + b Ano Ano R T::operator +=(S b); R operator +=(T a, S b);
Odečítání kombinované s přiřazením -= a -= b a = a - b Ano Ano R T::operator -=(S b); R operator -=(T a, S b);
Násobení kombinované s přiřazením *= a *= b a = a * b Ano Ano R T::operator *=(S b); R operator *=(T a, S b);
Dělení spojené se zadáním /= a /= b a = a / b Ano Ano R T::operator /=(S b); R operator /=(T a, S b);
Zbytek dělení v kombinaci se zadáním [poznámka 1] %= a %= b a = a % b Ano Ano R T::operator %=(S b); R operator %=(T a, S b);
Bitové "AND" kombinované s přiřazením &= a &= b a = a & b Ano Ano R T::operator &=(S b); R operator &=(T a, S b);
Bitové "OR" (nebo) v kombinaci s přiřazením |= a |= b a = a | b Ano Ano R T::operator |=(S b); R operator |=(T a, S b);
Bitové exkluzivní OR (xor) v kombinaci s přiřazením ^= a ^= b a = a ^ b Ano Ano R T::operator ^=(S b); R operator ^=(T a, S b);
Bitový posun doleva v kombinaci s přiřazením <<= a <<= b a = a << b Ano Ano R T::operator <<=(S b); R operator <<=(T a, S b);
Bitový posun doprava kombinovaný s přiřazením [poznámka 4] >>= a >>= b a = a >> b Ano Ano R T::operator >>=(S b); R operator >>=(T a, S b);

Operátory pro práci s ukazateli a členy třídy

Operátor Syntax Přetížitelné Implementováno v C Příklad
Člen typu T Definice mimo třídu
Přístup k prvku pole a[b] Ano Ano R T::operator [](S b);
n/a
Nepřímé odkazování ("objekt, na který ukazuje ") *a Ano Ano R T::operator *(); R operator *(T a);
Odkaz ("adresa " ) &a Ano Ano R T::operator &(); R operator &(T a);
Odkazování na člen struktury ("člen b objektu, na který ukazuje a ") a->b Ano Ano R* T::operator ->();[poznámka 5]
n/a
Odkazování na člen struktury ("člen b objektu a ") a.b Ne Ano n/a
Člen, na který ukazuje b v objektu, na který ukazuje a [poznámka 6] a->*b Ano Ne R T::operator ->*(S b); R operator ->*(T a, S b);
Člen označený b v objektu a a.*b Ne Ne n/a

Ostatní operátoři

Operátor Syntax Přetížitelné Implementováno v C Příklad
Člen typu T Definice mimo třídu
Funktor a(a1, a2) Ano Ano R T::operator ()(S a1, U a2, ...); n/a
Operátor čárky a, b Ano Ano R T::operator ,(S b); R operator ,(T a, S b);
Ternární podmíněný provoz a ? b : c Ne Ano n/a
Operátor rozšíření rozsahu a::b Ne Ne n/a
Vlastní literály (zavedené v C++ 11) "a"_b Ano Ne n/a R operator "" _b(T a)
Sizeof (velikost) sizeof(a)[poznámka 7]
sizeof(type)
Ne Ano n/a
Zarovnání ( zarovnání ) alignof(type)nebo [poznámka 8]_Alignof(type) Ne Ano n/a
Introspekce typeid(a)
typeid(type)
Ne Ne n/a
Typové odlévání (type) a Ano Ano T::operator R(); n/a
[poznámka 9]
Alokace paměti new type Ano Ne void* T::operator new(size_t x); void* operator new(size_t x);
Alokace paměti pro pole new type[n] Ano Ne void* T::operator new[](size_t x); void* operator new[](size_t x);
Uvolnění paměti delete a Ano Ne void T::operator delete(void* x); void operator delete(void* x);
Uvolnění paměti obsazené polem delete[] a Ano Ne void T::operator delete[](void* x); void operator delete[](void* x);

Poznámky:

  1. 1 2 Operátor % pracuje pouze s celými čísly. Pro čísla s pohyblivou řádovou čárkou použijte funkci () ze souboru " math.h " .fmod
  2. 1 2 Pro rozlišení mezi operátory prefix a suffix (postfix) byl k operátorům postfix přidán nepoužitý parametr formálního typu . Tento parametr často není ani pojmenován.int
  3. 1 2 V knihovně iostream se operátory " " a " " používají k práci se streamovaným výstupem a vstupem.<<>>
  4. 1 2 Podle standardu C99 je posunutí záporného čísla doprava chování definované implementací (viz nespecifikované chování ). Mnoho kompilátorů , včetně gcc (viz dokumentace archivovaná 22. září 2019 na Wayback Machine  ) implementuje aritmetický posun , ale standard nezakazuje implementovat logický posun .
  5. Návratový typ operátoru " " musí být typ, na který se operátor " " vztahuje , jako například ukazatel. Pokud je " " typu " " a třída " " přetěžuje operátor " ", výraz " " se rozšíří jako " ".operator->()->xCCoperator->()x->yx.operator->()->y
  6. Viz příklad v článku Wayback Machine Archived 17. května 2013 „Implementing a Smart Pointer Operator “ od Scotta Myerse z Dr. Dobb's journal , vydání z října 1999. ->*
  7. Operátor se obvykle píše se závorkami. Pokud je operandem název proměnné, jsou závorky volitelné. Pokud je operandem název typu, jsou závorky povinné.sizeof
  8. Jazykový standard C++ definuje alignof. Podobný operátor ve standardním jazyce C se nazývá _Alignof.
  9. U operátoru přetypování není návratový typ explicitně specifikován, protože je stejný jako název operátoru.

Přednost operátora

Tato tabulka uvádí prioritu a asociativitu operátorů. Operátory uvedené v tabulce výše (dříve) mají vyšší prioritu (přednost hodnocení). Při zvažování výrazu budou operátory s vyšší prioritou vyhodnoceny před operátory s nižší prioritou. Pokud je ve stejné buňce uvedeno několik operátorů, mají stejnou prioritu a jsou vyhodnoceny v pořadí určeném asociativitou. Priorita operátorů se při jejich přetížení nemění.


Tato tabulka priorit je ve většině případů s následujícími výjimkami dostačující. Ternární operátor "?:" může obsahovat operátor "čárka" nebo přiřazení v prostředním výrazu, ale kompilátor interpretuje kód " " jako " ", a ne jako nesmyslný výraz " "". S výrazem mezi a se tedy zachází, jako by byl v závorkách. a ? b, c : da ? (b, c) : d(a ? b), (c : d)?:

Priorita Operátor Popis Asociativnost
jeden

Nejvyšší

:: Rozlišení rozsahu Ne
2 ++ Přírůstek přípony Zleva doprava
-- Snížení přípony
() Volání funkce
[] Převzetí prvku pole
. Výběr prvku podle odkazu
-> Výběr prvku pomocí ukazatele
typeid() RTTI (pouze C++; viz typid )
const_cast Typ casting (C++) (viz const cast )
dynamic_cast Typ casting (C++) (viz dynamické casting )
reinterpret_cast Psaní slovních hříček (C++) (viz reinterpret_cast )
static_cast Typ odlévání (C++) (viz statické obsazení )
3 ++ přírůstek předpony Zprava doleva
-- předpona dekrementace
+ unární plus
- unární mínus
! Logické NE
~ Bitově NE
(type) Typové odlévání
* Dereferencování ukazatele
& Převzetí adresy objektu
sizeof Sizeof (velikost)
new,new[] Dynamická alokace paměti (C++)
delete,delete[] Uvolnění dynamické paměti (C++)
čtyři .* Ukazatel na člena (C++) Zleva doprava
->* Ukazatel na člena (C++)
5 * Násobení
/ Divize
% Získání zbytku divize
6 + Přidání
- Odčítání
7 << Bitový posun doleva
>> Bitový posun doprava
osm < Méně
<= Méně nebo stejně
> Více
>= Více nebo stejné
9 == Rovnost
!= Nerovnost
deset & Bitové AND (a)
jedenáct ^ Bitové XOR (xor)
12 | Bitové NEBO (nebo)
13 && logické AND
čtrnáct || Logické NEBO
patnáct ?: Ternární podmíněný provoz Zprava doleva
= Úkol
+= Sčítání v kombinaci se zadáním
-= Odečítání kombinované s přiřazením
*= Násobení kombinované s přiřazením
/= Dělení spojené se zadáním
%= Výpočet zbytku dělení v kombinaci se zadáním
<<= Bitový posun doleva v kombinaci s přiřazením
>>= Bitový posun doprava v kombinaci s přiřazením
&= Bitové "AND" kombinované s přiřazením
|= Bitové "OR" kombinované s přiřazením
^= Bitové exkluzivní OR (xor) v kombinaci s přiřazením
throw Throw Exception Operator (C++)
16 , Operátor čárky Zleva doprava

Popis

Kompilátor používá tabulku priorit k určení pořadí, ve kterém jsou operátory vyhodnocovány.

  • Například ++x*3by bylo nejednoznačné bez jakýchkoli pravidel přednosti. Z tabulky můžeme říci, že x je nejprve spojeno s operátorem ++ a teprve potom s operátorem * , takže bez ohledu na akci operátoru ++ je tato akce pouze na x (a ne na x*3). Výraz je tedy ekvivalentní ( ++x, x*3).
  • Podobně s kódem 3*x++, kde tabulka uvádí, že přírůstek se vztahuje pouze na x a ne na 3*x. Funkčně je tento výraz ekvivalentní ( ), pokud dočasnou proměnnou vyjádříte jako tmp .tmp=x, x++, tmp=3*tmp, tmp

Operátorská vazba ve standardech C a C++ je definována z hlediska gramatiky jazyka, nikoli z hlediska tabulky. To může způsobit konflikt. Například v C je syntaxe podmíněného příkazu:

logický - NEBO - výraz ? výraz : podmíněný - výraz

A v C++:

logický - NEBO - výraz ? výraz : přiřazení - výraz

Z tohoto důvodu výraz:

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

budou v obou jazycích vnímány odlišně. V C je výraz syntakticky nesprávný, protože výsledek podmíněného příkazu nemůže sloužit jako lvalue (tj. levá strana příkazu přiřazení).

V C++ bude výraz analyzován jako platný: [1]

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

Priorita bitových logických operátorů je poněkud neintuitivní [2] . Koncepčně &, a |jsou stejné aritmetické operátory jako *a +resp.

Výraz je syntakticky považován za výraz , ale výraz je ekvivalentní výrazu . Z tohoto důvodu je často nutné použít závorky k explicitnímu určení pořadí hodnocení. a & b == 7a & (b == 7)a + b == 7(a + b) == 7

Synonyma operátorů v C++

Standard C++ definuje [3] digrafy pro některé operátory:

Digraph Ekvivalentní řetězec
a &&
bitand &
a_ekv &=
nebo ||
bitor |
nebo_ekv |=
xor ^
xor_eq ^=
ne !
ne_rov !=
kompl ~

Digrafy lze používat stejně jako operátory, jsou to synonyma pro operátory. Například digraf " " lze použít k nahrazení operátorů "bitový AND" a "získání adresy" nebo v definici typů odkazů. Kód „ “ je tedy ekvivalentní kódu „ “. bitandint bitand ref = n;int & ref = n;

Standard ANSI/ISO C definuje uvedené digrafy jako konstanty #define(viz preprocesor ). Konstanty jsou definovány v záhlaví souboru " iso646.h". Pro kompatibilitu s C definuje standard C++ fiktivní hlavičkový soubor " ciso646".

Poznámky

  1. Má ternární operátor C/C++ skutečně stejnou přednost jako operátory přiřazení? . přetečení zásobníku. Získáno 22. září 2019. Archivováno z originálu 6. srpna 2020.
  2. Historie (downlink) . Získáno 11. ledna 2013. Archivováno z originálu 22. června 2013. 
  3. ISO/IEC JTC1/SC22/WG21 - C++ Standards Committee . ISO/IEC 14882:1998(E) Programovací  jazyk C++ . - Mezinárodní skupina pro standardizaci programovacího jazyka C++, 1998. - S. 40-41.

Odkazy