Questa è una lista degli operatori nei linguaggi di programmazione C e C++. Tutti gli operatori seguenti sono implementabili in quest'ultimo linguaggio, mentre invece altri non lo sono in C, come nel caso degli operatori di conversione di tipo (casting), ossia const_cast, static_cast, dynamic_cast, e reinterpret_cast[1][2][3].
Molti degli operatori disponibili in C e C++ sono implementabili pure in altri linguaggi della cosiddetta “famiglia C”, quali C#, D, ma anche Java, Perl e PHP, mantenendo le medesime caratteristiche mostrate (arietà, posizione e associatività)[4][5].
Sintassi degli operatori
[modifica | modifica wikitesto]Nelle tabelle seguenti, a, b e c rappresentano valori validi qualsiasi (literals, valori da variabili, oppure return value) o, in alcuni casi specifici, nomi di oggetti o lvalues. R, S e T indicano qualsiasi tipo, mentre K indica un tipo di classe o un tipo enum[6][7].
Operatori aritmetici
[modifica | modifica wikitesto]Tutti gli operatori aritmetici esistono sia in C e C++ e possono essere, come già indicato, sovraccaricati solo in C++[8].
| Nome operatore | Sintassi | Esempi di implementazione in C++ | ||
|---|---|---|---|---|
| Come membro della classe K | Fuori dalla classe | |||
| Addizione | a+b |
R K::operator +(S b); |
R operator +(K a, S b); | |
| Sottrazione | a-b |
R K::operator -(S b); |
R operator -(K a, S b); | |
| Unario più | +a |
R K::operator +(); | R operator +(K a); | |
| Unario meno | -a | R K::operator -(); | R operator -(K a); | |
| Moltiplicazione | a * b |
R K::operator *(S b); |
R operator *(K a, S b); | |
| Divisione | a / b |
R K::operator /(S b); |
R operator /(K a, S b); | |
| Modulo | a % b |
R K::operator %(S b); |
R operator %(K a, S b); | |
| Incremento | Prefisso | ++a |
R& K::operator ++(); |
R& operator ++(K& a); |
| Postfisso | a++ |
R K::operator ++(int); |
R operator ++(K& a, int); | |
| Il C++ utilizza il parametro fittizio senza nome int per differenziare gli operatori di incremento prefisso e postfisso. | ||||
| Decremento | Prefisso | --a |
R& K::operator --(); |
R& operator --(K& a); |
| Postfisso | a-- |
R K::operator --(int); |
R operator --(K& a, int); | |
| Il C++ utilizza il parametro fittizio senza nome int per differenziare gli operatori di incremento prefisso e postfisso. | ||||
Operatori relazionali
[modifica | modifica wikitesto]Tutti gli operatori di confronto possono essere sovraccaricati solo in C++. Dal C++20, l'operatore di disuguaglianza viene generato automaticamente se viene definito operator== e tutti e quattro gli operatori relazionali vengono generati automaticamente se viene definito operator<=>.
| Nome operatore | Sintassi | Incluso in C | Esempi di implementazione in C++ | |
|---|---|---|---|---|
| Come membro della classe K | Fuori dalla classe | |||
| Uguale | a = b |
Sì | bool K::operator ==(S const& b) const; |
bool operator ==(K const& a, S const& b); |
| Diverso | a != b | Sì | bool K::operator !=(S const& b) const; |
bool operator !=(K const& a, S const& b); |
| Maggiore di | a > b | Sì | bool K::operator >(S const& b) const; |
bool operator >(K const& a, S const& b); |
| Minore di | a < b | Sì | bool K::operator <(S const& b) const; |
bool operator <(K const& a, S const& b); |
| Maggiore o uguale a | a >= b | Sì | bool K::operator >=(S const& b) const; |
bool operator >=(K const& a, S const& b); |
| Minore o uguale a | a <= b | Sì | bool K::operator <=(S const& b) const; |
bool operator <=(K const& a, S const& b); |
Operatori logici (o booleani)
[modifica | modifica wikitesto]Tutti gli operatori logici (o booleani[9]) sono esistenti sia in C che in C++ e possono essere chiaramente sovraccaricati solo in quest'ultimo linguaggio di programmazione.
Nonostante la possibilità di sovraccarico in C++, tale operazione è sconsigliata con AND logico e OR logico sia sconsigliato perché, come operatori sovraccaricati, si comporterebbero come normali chiamate di funzione, il che significa che entrambi i loro operandi verrebbero valutati, perdendo di conseguenza la loro importante valutazione di McCarthy. [10]
| Nome dell'operatore | Sintassi | Esempi di implementazione in C++ | |
|---|---|---|---|
| Come membro della classe K | Fuori dalla classe | ||
| NOT logico | ! a |
bool K::operator !(); |
bool operator !(K a); |
| AND logico | a && b |
bool K::operator &&(S b); |
bool operator &&(K a, S b); |
| OR logico | a || b |
bool K::operator ||(S b); |
bool operator ||(K a, S b); |
Operatori bit a bit
[modifica | modifica wikitesto]Tutti gli operatori bit a bit (o di manipolazione dei bit) esistono sia C che C++ e possono essere sovraccaricati soltanto nel linguaggio inventato da Bjarne Stroustrup[11].
| Nome dell'operatore | Sintassi | Esempi di implementazione in C++ | |
|---|---|---|---|
| Come membro della classe K | Fuori dalla classe | ||
| Complemento a uno (inversione di tutti i bit) | ~a |
R K::operator ~(); |
R operator ~(K a); |
| AND bit a bit | a & b |
R K::operator &(S b); |
R operator &(K a, S b); |
| OR inclusivo bit a bit | a | b |
R K::operator |(S b); |
R operator |(K a, S b); |
| OR esclusivo bit a bit (OR exclusive, XOR) | a ^ b |
R K::operator ^(S b); |
R operator ^(K a, S b); |
| Spostamento di tutti i bit verso sinistra | a << b |
R K::operator <<(S b); |
R operator <<(K a, S b); |
| Spostamento di tutti i bit verso destra | a >> b |
R K::operator >>(S b); |
R operator >>(K a, S b); |
Operatori ed espressioni di assegnamento
[modifica | modifica wikitesto]Tutti gli operatori e le espressioni di assegnamento sono esistenti sia in C che in C++ e possono essere chiaramente sovraccaricate solo in quest'ultimo linguaggio di programmazione.
Per gli operatori indicati, la semantica dell'espressione di assegnazione combinata incorporata a ⊚= b è equivalente a a = a ⊚ b, eccetto per il fatto che a viene valutata una sola volta.
| Tipologia assegnamento | Sintassi | Esempi di implementazione in C++ | |
|---|---|---|---|
| Come membro della classe K | Fuori dalla classe | ||
| Espressione semplice di assegnamento | a = b |
R& K::operator =(S b); |
N.D. |
| Assegnamenti composti | 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); | |
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); | |
Operatori membro e puntatore
[modifica | modifica wikitesto]| Nome operatore[12] | Sintassi | Ammette overload (sovraccarico) in C++ | Implementabile in C | Esempi di implementazione in C++ | |
|---|---|---|---|---|---|
| Come membro della classe K | Fuori dalla classe | ||||
| Indicizzazione | a[b] |
Sì | Sì | R& K::operator [](S b);
|
N.D. |
| Deferenziazione | *a |
Sì | Sì | R& K::operator *(); | R& operator *(K a); |
| Indirizzo | &a |
Sì | Sì | R* K::operator &(); | R* operator &(K a); |
| Deferenziazione e selezione | a->b |
Sì | Sì | R* K::operator ->(); | N.D. |
| Selezione (object.member) | a.b |
No | Sì | N.D. | N.D. |
| Deferenziazione e selezione con puntatore a membro | a->*b |
Sì | No | R& K::operator ->*(S b); | R& operator ->*(K a, S b); |
| Selezione con puntatore a membro | a.*b |
No | No | N.D. | N.D. |
Altri operatori
[modifica | modifica wikitesto]| Nome operatore | Sintassi | Ammette overload (sovraccarico) in C++ | Implementabile in C | Esempi di implementazione in C++ | |
|---|---|---|---|---|---|
| Come membro della classe K | Fuori dalla classe | ||||
| Chiamata di funzione | a(a1, a2) |
Sì | Sì | R K::operator ()(S a, T b, ...); | |
| Virgola | a, b |
Sì | Sì | R K::operator ,(S b); |
R operator ,(K a, S b); |
| Espressione condizionale | a ? b : c |
No | Sì | N.D. | N.D. |
| Risolutore di visibilità | a::b |
No | No | N.D. | N.D. |
| Dimensione di oggetto o di tipo (sizeof) | sizeof a
|
No | Sì | N.D. | N.D. |
| Conversione di tipo static_cast | static_cast<R>(a) |
Sì | No | K::operator R();
|
N.D. |
| Conversione const const_cast | const_cast<R>(a) |
No | No | N.D. | N.D. |
| Allocazione | new R |
Sì | No | void* K::operator new(size_t x); |
void* operator new(size_t x); |
| Allocazione di array | new R[n] |
Sì | No | void* K::operator new[](size_t a); |
void* operator new[](size_t a); |
| Deallocazione | delete a |
Sì | No | void K::operator delete(void* a); |
void operator delete(void* a); |
| Deallocazione di array | delete[] a |
Sì | No | void K::operator delete[](void* a); |
void operator delete[](void* a); |
Overloading degli operatori
[modifica | modifica wikitesto]C++ possiede molti operatori già predefiniti in grado di operare su vari tipi di dato, perciò si può parlare di “operatori già sovraccaricati”. Per esempio l’operatore + può essere implementato per sommare sia due variabili di tipo int (interi), sia due variabili di tipo float o double (variabili a virgola mobile).
Oltre a quando detto in precedenza, il programmatore può anche “estendere” l’operatività di ciascuno di essi; per esempio operandi complessi definiti con le classi, si potrebbero trattare anche come se fossero dati semplici[1].
In C++ è possibile sovraccaricare tutti gli operatori predefiniti, con l’eccezione su accesso al membro (.), indirezione di accesso al membro (.*) e risoluzione di ambito (::).
Nel caso degli operatori, il numero degli operandi e la priorità dell’operatore sovraccaricato sono le stesse dell’operatore predefinito, mentre il nuovo operatore può essere definito come una funzione membro oppure come una funzione friend (funzione amica)[14].
Proprietà degli operatori
[modifica | modifica wikitesto]Ogni operatore possiede delle proprietà, in modo tale da permettere l'interpretazione univoca del significato di ogni singola espressione. Gli esempi che seguono sono tutti applicabili al linguaggio C++ e, a seconda dei casi, anche al C[15].
Posizione
[modifica | modifica wikitesto]Un operatore può precedere gli operandi (o argomenti), seguirli oppure né precederli né seguirli[12]. In questi casi parleremo rispettivamente di operatori prefissi, postfissi oppure infissi.
Numero di operandi
[modifica | modifica wikitesto]Ogni operatore può avere un numero diverso di operandi (arietà).
a[b]
Nel caso riportato, l'operatore di indicizzazione possiede due operandi, ossia le parentesi quadre. L'arietà può essere anche di tre operandi, come nel caso degli operatori condizionali, riportato di seguito:
e1 ? e2 : e3
Precedenza degli operatori
[modifica | modifica wikitesto]Ogni operatore possiede una propria precedenza[16][17], rappresentata attraverso un numero naturale tra 1 e 18 in ordine decrescente, dove più è piccolo il numero, maggiore sarà la priorità; per esempio un operatore con priorità 1 avrà maggiore priorità su un operatore con priorità 13.
Nell'esempio che segue è possibile osservare una semplice applicazione pratica delle precedenze:
#include <iostream>
using namespace std;
int main () {
int a = 5;
int b = 6;
int c = 8;
int op = a+b*c;
cout << op << endl; // Stampa a schermo
return 0;
}
L'operatore moltiplicazione (*) possiede priorità 5, mentre l'operatore addizione (+) possiede priorità 6; pertanto il risultato a schermo sarà 53 e non 19.
Associatività degli operatori
[modifica | modifica wikitesto]L'associatività indica l'ordine in cui vengono eseguiti gli operatori aventi la stessa priorità tra loro[12]. Viene riportato un semplice esempio con gli operatori di divisione (priorità 5).
#include <iostream>
using namespace std;
int main (){
float a = 5.0;
float b = 6.0;
float c = 8.0;
float div = a/b/c;
cout << div << endl; // Stampa a schermo
return 0;
}
Nell'esempio precedente la stampa a schermo sarà 0.104167 perché l'operatore di divisione segue associatività a sinistra e, quindi, il calcolatore avrà eseguito la seguente equazione: .
Tabella delle precedenze e delle associatività
[modifica | modifica wikitesto]Nella tabella seguente sono elencati gli operatori di C e C++ in ordine di priorità con le loro rispettive associatività. Essi sono sempre implementabili su C++, mentre, quelli appositamente indicati nella penultima colonna da sinistra, non lo sono in C[12][17].
| Priorità | Operatore | Nome | Implementabile in C | Associatività |
|---|---|---|---|---|
| 1
(priorità massima) |
class-name :: member
|
Risolutore di visibilità | No | sinistra |
:: member |
Risolutore globale di visibilità | No | destra | |
| 2 | object . member |
Selezione | Sì | sinistra |
pointer -> member |
Deferenziazione e selezione | Sì | sinistra | |
array[ rvalue ] |
Indicizzazione | Sì | sinistra | |
function ( actual-argument-list ) |
Chiamata di funzione | Sì | sinistra | |
lvalue ++ |
Postincremento | Sì | destra | |
lvalue -- |
Postdecremento | Sì | destra | |
static_cast type<rvalue> |
Conversione di tipo | No | sinistra | |
const_cast type<rvalue> |
Conversione const | No | sinistra | |
| 3 | sizeof object
|
Dimensione
di oggetto di tipo |
Sì | destra |
++ lvalue |
Preincremento | Sì | destra | |
-- lvalue |
Predecremento | Sì | destra | |
~ rvalue |
Complemento bit a bit | Sì | destra | |
! rvalue |
Negazione | Sì | destra | |
- rvalue |
Meno unitario | Sì | destra | |
+ rvalue |
Più unitario | Sì | destra | |
& rvalue |
Indirizzo | Sì | destra | |
* rvalue |
Deferenziazione | Sì | destra | |
new type |
Allocazione | No | destra | |
new type[] |
Allocazione di array | No | destra | |
delete pointer |
Deallocazione | No | destra | |
delete[] pointer |
Deallocazione di array | No | destra | |
| 4 | object .* pointer-to-member |
Selezione con puntatore a membro | No | sinistra |
pointer ->* pointer-to-member |
Deferenziazione e selezione con puntatore a membro | No | sinistra | |
| 5 | rvalue * rvalue |
Moltiplicazione | Sì | sinistra |
rvalue / rvalue |
Divisione | Sì | sinistra | |
rvalue % rvalue |
Modulo | Sì | sinistra | |
| 6 | rvalue + rvalue |
Addizione | Sì | sinistra |
rvalue - rvalue |
Sottrazione | Sì | sinistra | |
| 7 | rvalue << rvalue |
Traslazione sinistra | Sì | sinistra |
rvalue >> rvalue |
Traslazione destra | Sì | sinistra | |
| 8 | rvalue < rvalue |
Minore | Sì | sinistra |
rvalue <= rvalue |
Minore o uguale | Sì | sinistra | |
rvalue > rvalue |
Maggiore | Sì | sinistra | |
rvalue >= rvalue |
Maggiore o uguale | Sì | sinistra | |
| 9 | rvalue == rvalue |
Uguale | Sì | sinistra |
rvalue != rvalue |
Diverso | Sì | sinistra | |
| 10 | rvalue & rvalue |
AND bit a bit | Sì | sinistra |
| 11 | rvalue ^ rvalue |
OR esclusivo bit a bit | Sì | sinistra |
| 12 | rvalue | rvalue |
OR bit a bit | Sì | sinistra |
| 13 | rvalue && rvalue |
AND logico | Sì | sinistra |
| 14 | rvalue || rvalue |
OR logico | Sì | sinistra |
| 15 | co_await
|
Coroutine | No | destra |
| 16 | rvalue ? rvalue : rvalue |
Espressione condizionale | Sì | sinistra |
| 17 | lvalue = rvalue |
Assegnamento | Sì | destra |
lvalue += rvalue |
Addizione e assegnamento | Sì | destra | |
lvalue -= rvalue |
Sottrazione e assegnamento | Sì | destra | |
lvalue *= rvalue |
Moltiplicazione e assegnamento | Sì | destra | |
lvalue /= rvalue |
Divisione e assegnamento | Sì | destra | |
lvalue %= rvalue |
Modulo e assegnamento | Sì | destra | |
lvalue &= rvalue |
AND bit a bit e assegnamento | Sì | destra | |
lvalue |= rvalue |
OR bit a bit e assegnamento | Sì | destra | |
lvalue ^= rvalue |
OR esclusivo bit a bit e assegnamento | Sì | destra | |
lvalue <<= rvalue |
Traslazione a sinistra e assegnamento | Sì | destra | |
lvalue =>> rvalue |
Traslazione a destra e assegnamento | No | destra | |
| 18
(priorità minima) |
expression , expression |
Virgola | Sì | sinistra |
Critiche sulle precedenze degli operatori
[modifica | modifica wikitesto]La precedenza degli operatori logici bitwise è stata al centro di numerose critiche[18][19], poiché concettualmente, & e | sono operatori aritmetici come * e +.
Per esempio, l'espressione a & b == 7 viene sintatticamente analizzata come a & (b == 7), mentre l'espressione a + b == 7 viene analizzata come (a + b) == 7. Ciò richiede l'uso delle parentesi più spesso di quanto sarebbe altrimenti necessario.
Storicamente, non esisteva una distinzione sintattica tra gli operatori bit a bit e quelli logici. Nei linguaggi BCPL, B e nelle prime versioni di C, gli operatori && e || non esistevano proprio; invece, & | aveva un significato diverso a seconda che venisse usato in un “contesto di valore di verità” (cioè quando ci si aspettava il ritorno di un valore booleano, come in if (a==b & c) {...} e si comportava come un operatore logico, ma in c = a & b si comportava invece come un operatore bit a bit).
La sintassi attuale è stata mantenuta soltanto per consentire la retrocompatibilità con le installazioni già esistenti.
Peraltro, in C++ (e nelle versioni successive di C) le operazioni di uguaglianza, con l'eccezione dell'operatore di confronto logico a tre, producono valori di tipo bool che sono concettualmente un singolo bit (1 o 0) e come tali non appartengono propriamente alle operazioni bit a bit.
Sinonimi in C++
[modifica | modifica wikitesto]C++ definisce una serie di keywords che possono essere implementate come sinonimi rispetto agli operatori[20]; tali definizioni non sono assolutamente implementabili nel linguaggio C.
| Keyword | Operator |
|---|---|
and |
&& |
and_eq |
&= |
bitand |
& |
bitor |
| |
compl |
~ |
not |
! |
not_eq |
!= |
or |
|| |
or_eq |
|= |
xor |
^ |
xor_eq |
^= |
Questi possono essere utilizzati esattamente come sostituti dei rispettivi simboli di punteggiatura; ciò significa, per esempio, che le espressioni (a > 0 AND NOT flag) e (a > 0 && !flag) avranno un significato assolutamente identico.
Note
[modifica | modifica wikitesto]- 1 2 Luis Joyanes Aguilar, Fondamenti di programmazione in C++. Algoritmi, strutture dati e oggetti, II edizione in lingua italiana, Madrid-Milano, McGraw-Hill Education, 2008, ISBN 978-88-386-6477-9.
- ↑ Stanley Lippman, Josée Lajoie e Barbara Moo, C++ Primer, V edizione, Addison-Wesley Professional, 2013, ISBN 978-0321714114.
- ↑ Conversione di tipo, su HTML.it. URL consultato il 14 settembre 2024.
- ↑ Il linguaggio C#, su www.andreaminini.com. URL consultato il 30 agosto 2024.
- ↑ Operator Overloading - D Programming Language, su dlang.org. URL consultato il 30 agosto 2024.
- ↑ 1.3 Operatori., su www.math.unipd.it. URL consultato il 30 agosto 2024.
- ↑ Operatori booleani, su HTML.it. URL consultato il 30 agosto 2024.
- ↑ (EN) C++ | Definition, History, & Facts | Britannica, su www.britannica.com. URL consultato il 30 agosto 2024.
- ↑ L'accezione booleana è stata coniata in onore del matematico George Boole.
- ↑ isocpp.org, https://isocpp.org/wiki/faq/operator-overloading.
- ↑ Linguaggio c++ - Enciclopedia, su Treccani. URL consultato il 30 agosto 2024.
- 1 2 3 4 Andrea Domenici e Graziano Frosini, Introduzione alla programmazione ed elementi di strutture dati con il linguaggio C++, collana "Informatica", diretta da A. L. Frisiani, VIII edizione, Milano/Pisa, ISBN 978-8846462022.
- ↑ Per le conversioni definite dall'utente, il tipo di ritorno corrisponde implicitamente e necessariamente al nome dell'operatore, a meno che il tipo non sia dedotto. (es.
operator auto(), operator decltype(auto)()etc.). - ↑ Marco Cococcioni, Le classi nel linguaggio C++ (PDF), Dipartimento di Ingegneria dell'Informazione dell'Università di Pisa.
- ↑ Marco Cococcioni, Programmazione in stile C, utilizzando il linguaggio C++ (PDF), Dipartimento di Ingegneria dell'Informazione dell'Università di Pisa.
- ↑ The ISO C 1999 standard, section 6.5.6 note 71 (Technical report). ISO. 1999.
- 1 2 Marco Cococcioni, Priorità degli operatori (PDF), Dipartimento di Ingegneria dell'Informazione dell'Università di Pisa.
- ↑ Chistory, su www.bell-labs.com. URL consultato il 30 agosto 2024.
- ↑ Re^10: next unless condition, su www.perlmonks.org. URL consultato il 30 agosto 2024.
- ↑ ISO/IEC 14882:1998(E) Programming Language C++. open-std.org – The C++ Standards Committee. 1 September 1998. pp. 40–41.
Bibliografia
[modifica | modifica wikitesto]- (EN) Bjarne Stroustrup, The C++ Programming Language, Addison-Wesley, ISBN 978-0-201-70073-2.
- Andrea Domenici, Graziano Frosini, Introduzione alla programmazione ed elementi di strutture dati con il linguaggio C++, Franco Angeli Editore, 2013, p. 480, ISBN 978-88-464-6202-2.
- Marco Cococcioni, Fondamenti di programmazione (PDF), Dipartimento di Ingegneria dell'Informazione dell'Università di Pisa.
- (ES) Luis Joyanes Aguilar, Fondamenti di programmazione in C++. Algoritmi, strutture dati e oggetti, Madrid-Milano, McGraw-Hill Education, ISBN 978-88-386-6477-9.
Voci correlate
[modifica | modifica wikitesto]Collegamenti esterni
[modifica | modifica wikitesto]- Volle, Adam. "C++". Encyclopedia Britannica, 19 Jun. 2024, https://www.britannica.com/technology/C-computer-language;
- Microsoft C++, C, and Assembler documentation.








