Operatori aritmetici

Linguaggio C++

Argomenti generali
Controllo del flusso
Esecuzione condizionale esecuzione condizionale

if

Dichiarazioni di iterazione (loop)

for

range-for (C++11)

Dichiarazione di salto

continuebreak

gotoreturn

Funzioni
Dichiarazione di funzione
Dichiarazione di funzione lambda
inline specificatore
Specifiche di eccezione (fino al C++20)
noexcept specificatore (C++11)
Eccezioni
Namespaces
Tipi
Specificatori

decltype (C++11)

auto (C++11)

alignas (C++11)

const/volatile

constexpr (C++11)

Specificatori di durata di memorizzazione
Inizializzazione
Espressioni
Rappresentazioni alternative
Letterali
Booleano – Integer – Floating-point
Character – String – nullptr (C++11)
User-definito dall’utente (C++11)
Utilità
Attributi (C++11)
Tipi
typedef dichiarazione
Dichiarazione alias di tipo (C++11)
Casts
Conversioni implicite – Conversioni esplicite
static_castdynamic_cast
const_castreinterpret_cast
Allocazione della memoria
Classi
Classi-specifiche della funzione

Funzione virtuale

specificatore di override (C++11)

specificatore finale (C++11)

explicit (C++11)

static

Funzioni membro speciali

assegnazione di copia

assegnazione di spostamento (C++11)

Distruttore

Modelli

Specializzazione modello

Pacchetti di parametri (C++11)

Varie
Espressioni

Categorie di valori generali

(lvalue, rvalue, xvalue)

ordine di valutazione (punti sequenza)

espressioni costanti

espressioni non valutate

espressioni primarie

lambda-expression(C++11)

letterali

letterali interi

letterali a virgola mobilepunto fluttuante

letterali booleani

letterali di carattere incluse le sequenze di escape

letterali di stringa

letterale puntatore nullo(C++11)

letterale definito dall’utente(C++11)

Operatori

operatori di assegnazione: a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b

Incremento e decremento: ++a, --a, a++, a--

Operatori aritmetici:+a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b

Operatori logici: a||b, a&&b, !a

Operatori di confronto: a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)

Operatori di accesso ai membri: a, *a, &a, a->b, a.b, a->*b, a.*b

Altri operatori: a(...), a,b, a?b:c

new-expression

delete-expression

throw-expression

alignof

sizeof

sizeof…(C++11)

typeid

noexcept(C++11)

Fold expression(C++17)

Rappresentazioni alternative degli operatori

Precedenza e associatività

Overloading degli operatori

Confronti predefiniti (C++20)

Conversioni

Conversioni implicite

const_cast

static_cast

reinterpret_cast

dynamic_cast

Conversioni esplicite (T)a, T(a)

Conversione definita dall’utente

Restituisce il risultato di una specifica operazione aritmetica.

Nome dell’operatore Sintassi Sovraccaricabile Esempi di prototipi (per la classe T)
Dentro la definizione della classe Fuori dalla definizione della classe
unario più +a T T::operator+() const; T operator+(const T &a);
unario meno -a T::operator-() const; T operator-(const T &a);
aggiunta a + b T::operator+(const T2 &b) const; T operator+(const T &a, const T2 &b);
sottrazione a - b T::operator-(const T2 &b) const; T operator-(const T &a, const T2 &b);
moltiplicazione a * b T::operator*(const T2 &b) const; T operator*(const T &a, const T2 &b);
divisione a / b T::operator/(const T2 &b) const; T operator/(const T &a, const T2 &b);
modulo a % b T::operator%(const T2 &b) const; T operator%(const T &a, const T2 &b);
bitwise NOT ~a Yes T::operator~() const; T operator~(const T &a);
bitwise AND a & b Yes T::operator&(const T2 &b) const; T operator&(const T &a, const T2 &b);
bitwise OR a | b Yes T::operator|(const T2 &b) const; T operator|(const T &a, const T2 &b);
bitwise XOR a ^ b Yes T::operator^(const T2 &b) const; T operator^(const T &a, const T2 &b);
bitwise left shift a << b Yes T::operator<<(const T2 &b) const; T operator<<(const T &a, const T2 &b);
bitwise right shift a >> b Yes T::operator>>(const T2 &b) const; T operator>>(const T &a, const T2 &b);
Note

  • Tutti gli operatori built-in restituiscono valori, e la maggior parte dei sovraccarichi definiti dall’utente restituiscono anche valori in modo che gli operatori definiti dall’utente possano essere usati allo stesso modo dei built-in. Tuttavia, in un sovraccarico di operatore definito dall’utente, qualsiasi tipo può essere usato come tipo di ritorno (incluso void). In particolare, gli overload di inserimento e di estrazione dei flussi di operator<< e operator>> restituiscono T&.
  • T2 può essere qualsiasi tipo incluso T

  • 1 Spiegazione
    • 1.1 Conversioni
    • 1.2 Overflow
    • 1.3 Ambiente in virgola mobile
    • 1.4 Contrazione in virgola mobile
    • 1.5 Operatori aritmetici unari
    • 1.6 Operatori additivi
    • 1.7 Operatori moltiplicativi
    • 1.8 Operatori logici bitwise
    • 1.9 Operatori bitwise shift
  • 2 Libreria standard
    • 2.1 Operatori aritmetici unari
    • 2.2 Operatori additivi
    • 2.3 Operatori moltiplicativi
    • 2.4 Operatori logici bitwise
    • 2.5 Operatori bitwise shift
    • 2.6 Operatori di inserimento/estrazione di flussi
  • 3 Segnalazioni di difetti
  • 4 Vedi anche

Spiegazione

Tutti gli operatori aritmetici calcolano il risultato di una specifica operazione aritmetica e ne restituiscono il risultato. Gli argomenti non vengono modificati.

Conversioni

Se l’operando passato ad un operatore aritmetico è di tipo integrale o di enumerazione nonscopica, allora prima di qualsiasi altra azione (ma dopo la conversione da valore a valore, se applicabile), l’operando subisce una promozione integrale. Se un operando è di tipo array o funzione, vengono applicate le conversioni da array a puntatore e da funzione a puntatore.

Per gli operatori binari (eccetto gli shift), se gli operandi promossi hanno tipi diversi, viene applicato un ulteriore insieme di conversioni implicite, noto come conversioni aritmetiche usuali con l’obiettivo di produrre il tipo comune (accessibile anche tramite il tratto di tipo std::common_type). Se, prima di qualsiasi promozione integrale, un operando è di tipo enumerazione e l’altro operando è di un tipo a virgola mobile o di un diverso tipo di enumerazione, questo comportamento è deprecato. (dal C++20)

  • Se uno dei due operandi ha il tipo di enumerazione scoped, non viene eseguita alcuna conversione: l’altro operando e il tipo di ritorno devono avere lo stesso tipo
  • Altrimenti, se uno degli operandi è long double, l’altro operando viene convertito in long double
  • Altrimenti, se uno degli operandi è double, l’altro operando viene convertito in double
  • Altrimenti, se uno degli operandi è float, l’altro operando viene convertito in float
  • Altrimenti, l’operando ha tipo intero (perché bool, char, char8_t, char16_t, char32_t, wchar_t, e unscoped enumeration sono stati promossi a questo punto) e vengono applicate conversioni integrali per produrre il tipo comune, come segue:
  • Se entrambi gli operandi sono firmati o entrambi sono senza segno, l’operando con il rango di conversione minore è convertito nell’operando con il rango di conversione maggiore dell’intero
  • Altrimenti, se il rango di conversione dell’operando senza segno è maggiore o uguale al rango di conversione dell’operando firmato, l’operando firmato è convertito nel tipo dell’operando senza segno.
  • Altrimenti, se il tipo dell’operando firmato può rappresentare tutti i valori dell’operando senza segno, l’operando senza segno viene convertito nel tipo dell’operando firmato
  • Altrimenti, entrambi gli operandi vengono convertiti nella controparte senza segno del tipo dell’operando firmato.

Il rango di conversione sopra aumenta in ordine bool, signed char, short, int, long, long long. Il rango di qualsiasi tipo senza segno è uguale al rango del corrispondente tipo con segno. Il rango di char è uguale al rango di char firmato e char senza segno. I ranghi di char8_t, char16_t, char32_t, e wchar_t sono uguali ai ranghi dei loro tipi sottostanti.

Overflows

L’aritmetica degli interi senza segno viene sempre eseguita modulo 2n
dove n è il numero di bit in quel particolare intero. Ad esempio, per gli int senza segno, aggiungendo uno a UINT_MAX si ottiene 0, e sottraendo uno da 0 si ottiene UINT_MAX.

Quando un’operazione aritmetica intera firmata trabocca (il risultato non rientra nel tipo di risultato), il comportamento è indefinito, – le possibili manifestazioni di tale operazione includono:

  • si avvolge secondo le regole della rappresentazione (tipicamente complemento a 2),
  • si intrappola – su alcune piattaforme o a causa di opzioni del compilatore (es.g. -ftrapv in GCC e Clang),
  • si satura al valore minimo o massimo (su molti DSP),
  • è completamente ottimizzato dal compilatore.

Ambiente in virgola mobile

Se #pragma STDC FENV_ACCESS è supportato e impostato su ON, tutti gli operatori aritmetici in virgola mobile obbediscono all’attuale direzione di arrotondamento in virgola mobile e riportano errori aritmetici in virgola mobile come specificato in math_errhandling a meno che non facciano parte di un inizializzatore statico (nel qual caso le eccezioni in virgola mobile non vengono sollevate e la modalità di arrotondamento è quella più vicina)

Contrazione in virgola mobile

A meno che #pragma STDC FP_CONTRACT sia supportato e impostato a OFF, tutta l’aritmetica in virgola mobile può essere eseguita come se i risultati intermedi avessero intervallo e precisione infiniti, cioè sono permesse ottimizzazioni che omettono errori di arrotondamento ed eccezioni in virgola mobile. Per esempio, il C++ permette l’implementazione di (x*y) + z con una singola istruzione CPU fused multiply-add o l’ottimizzazione di a = x*x*x*x; come tmp = x *x; a = tmp*tmp.

Non legato alla contrattazione, i risultati intermedi dell’aritmetica in virgola mobile possono avere intervallo e precisione diversi da quelli indicati dal suo tipo, vedi FLT_EVAL_METHOD

In generale, lo standard C++ non garantisce la precisione delle operazioni in virgola mobile.

Operatori aritmetici unari

Le espressioni degli operatori aritmetici unari hanno la forma

+ espressione (1)
- espressione (2)
1) unario più (promozione).
Per l’operatore incorporato, l’espressione deve essere di tipo aritmetico, enumerazione nonscopica o puntatore. La promozione integrale viene eseguita sull’operando se ha un tipo di enumerazione integrale o unscoped e determina il tipo del risultato.
2) unario meno (negazione).
Per l’operatore incorporato, l’espressione deve avere un tipo aritmetico o unscoped enumeration. La promozione integrale viene eseguita sull’operando e determina il tipo del risultato.

L’operatore incorporato unario più restituisce il valore del suo operando. L’unica situazione in cui non è un no-op è quando l’operando ha un tipo integrale o un tipo di enumerazione unscoped, che viene cambiato dalla promozione integrale, ad esempio, converte char in int o se l’operando è soggetto alla conversione lvalue-to-rvalue, array-to-pointer, o function-to-pointer.

L’operatore unario integrato minus calcola il negativo del suo operando promosso. Per unsigned a, il valore di -a è 2b
-a, dove b è il numero di bit dopo la promozione.

Nella risoluzione di sovraccarico contro operatori definiti dall’utente, per ogni tipo aritmetico promosso A e per ogni tipo T, le seguenti firme di funzione partecipano alla risoluzione di sovraccarico:

A operator+(A)

T* operator+(T*)

A operator-(A)

Esegui questo codice
#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';}

Output:

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

Operatori additivi

Le espressioni degli operatori aritmetici additivi binari hanno la forma

lhs + rhs (1)
lhs - rhs (2)
1) addizione
Per l’operatore built-in operatore, lhs e rhs devono essere uno dei seguenti:

  • entrambi hanno un tipo aritmetico o unscoped enumeration. In questo caso, le usuali conversioni aritmetiche vengono eseguite su entrambi gli operandi e determinano il tipo del risultato.
  • uno è un puntatore a un tipo di oggetto completamente definito, l’altro ha un tipo di enumerazione integrale o unscoped. In questo caso, il tipo del risultato ha il tipo del puntatore.
2) sottrazione
Per l’operatore incorporato, lhs e rhs devono essere uno dei seguenti:

  • entrambi hanno tipo aritmetico o enumerazione unscoped. In questo caso, le usuali conversioni aritmetiche vengono eseguite su entrambi gli operandi e determinano il tipo del risultato.
  • lhs è un puntatore a un tipo di oggetto completamente definito, rhs ha un tipo di enumerazione integrale o unscoped. In questo caso, il tipo del risultato ha il tipo del puntatore.
  • entrambi sono puntatori agli stessi tipi di oggetto completamente definiti, ignorando i cv-qualificatori. In questo caso, il tipo di risultato è std::ptrdiff_t.

Con operandi di tipo aritmetico o di enumerazione, il risultato dell’operatore binario più è la somma degli operandi (dopo le consuete conversioni aritmetiche), e il risultato dell’operatore binario meno è il risultato della sottrazione del secondo operando dal primo (dopo le consuete conversioni aritmetiche), tranne che, se il tipo supporta l’aritmetica in virgola mobile IEEE (vedere std::numeric_limits::is_iec559),

  • se un operando è NaN, il risultato è NaN
  • infinito meno infinito è NaN e FE_INVALID è sollevato
  • infinito più l’infinito negativo è NaN e FE_INVALID è sollevato

Se uno degli operandi è un puntatore, si applicano le seguenti regole:

  • Un puntatore a un oggetto non-array è trattato come un puntatore al primo elemento di un array con dimensione 1.
  • Se il puntatore P punta al iesimo elemento di un array, allora le espressioni P+n, n+P e P-n sono puntatori dello stesso tipo che puntano rispettivamente al i+nesimo, i+nesimo e i-nesimo elemento dello stesso array. Il risultato dell’addizione dei puntatori può anche essere un puntatore uno-presso-fine (cioè il puntatore P tale che l’espressione P-1 punti all’ultimo elemento dell’array). Qualsiasi altra situazione (cioè i tentativi di generare un puntatore che non punti a un elemento della stessa matrice o uno oltre la fine) invoca un comportamento non definito.
  • Se il puntatore P punta al isimo elemento di una matrice, e il puntatore Q punta al jsimo elemento della stessa matrice, l’espressione P-Q ha il valore i-j, se il valore rientra in std::ptrdiff_t. Entrambi gli operandi devono puntare agli elementi della stessa matrice (o uno oltre la fine), altrimenti il comportamento è indefinito. Se il risultato non entra in std::ptrdiff_t, il comportamento è indefinito.
  • In ogni caso, se il tipo puntato è diverso dal tipo di elemento dell’array, trascurando le qualifiche cv, ad ogni livello se gli elementi sono essi stessi puntatori, il comportamento dell’aritmetica dei puntatori è indefinito. In particolare, l’aritmetica dei puntatori con puntatore alla base, che punta a un elemento di un array di oggetti derivati è indefinita.
  • Se il valore 0 viene aggiunto o sottratto da un puntatore, il risultato è il puntatore, invariato. Se due puntatori puntano allo stesso oggetto o sono entrambi oltre la fine dello stesso array, o entrambi sono puntatori nulli, allora il risultato della sottrazione è uguale a (std::ptrdiff_t)0.

Questi operatori aritmetici di puntatori permettono ai puntatori di soddisfare i requisiti del LegacyRandomAccessIterator.

Nella risoluzione di sovraccarico contro operatori definiti dall’utente, per ogni coppia di tipi aritmetici promossi L e R e per ogni tipo di oggetto T, le seguenti firme di funzione partecipano alla risoluzione di sovraccarico:

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

dove LR è il risultato delle usuali conversioni aritmetiche su L e R

Esegui questo codice
#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';}

Output:

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

Operatori moltiplicativi

Le espressioni dell’operatore aritmetico moltiplicativo binario hanno la forma

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
1) moltiplicazione
Per l’operatore integratoin operatore, lhs e rhs devono avere entrambi un tipo aritmetico o unscoped enumeration.
2) divisione
Per l’operatore incorporato, lhs e rhs devono avere entrambi il tipo aritmetico o di enumerazione unscoped.
3) resto
Per l’operatore incorporato, lhs e rhs devono avere entrambi il tipo di enumerazione integrale o unscoped

Per tutti e tre gli operatori, le solite conversioni aritmetiche vengono eseguite su entrambi gli operandi e determinano il tipo del risultato.

L’operatore binario * esegue la moltiplicazione dei suoi operandi (dopo le solite conversioni aritmetiche), tranne che per la moltiplicazione in virgola mobile,

  • la moltiplicazione di un NaN per qualsiasi numero dà NaN
  • la moltiplicazione di infinito per zero dà NaN e viene sollevato FE_INVALID

L’operatore binario / divide il primo operando per il secondo (dopo le normali conversioni aritmetiche).

Per gli operandi integrali, produce il quoziente algebrico.

Il quoziente è arrotondato nella direzione definita dall’implementazione.

(fino a C++11)

Il quoziente viene troncato verso zero (la parte frazionaria viene scartata).

(dal C++11)

Se il secondo operando è zero, il comportamento è indefinito, tranne che se è in corso una divisione in virgola mobile e il tipo supporta l’aritmetica in virgola mobile IEEE (vedere std::numeric_limits::is_iec559), allora:

  • se un operando è NaN, il risultato è NaN
  • dividendo un numero non zero per ±0.0 dà l’infinito con segno corretto e viene sollevato FE_DIVBYZERO
  • dividendo 0,0 per 0,0 dà NaN e viene sollevato FE_INVALID

L’operatore binario % produce il resto della divisione intera del primo operando per il secondo (dopo le consuete conversioni aritmetiche; si noti che gli operandi devono essere di tipo integrale). Se il quoziente a/b è rappresentabile nel tipo di risultato, (a/b)*b + a%b == a. Se il secondo operando è zero, il comportamento è indefinito. Se il quoziente a/b non è rappresentabile nel tipo di risultato, il comportamento di entrambi a/b e a%b è indefinito (ciò significa che INT_MIN%-1 è indefinito sui sistemi a complemento di 2)

Nota: Fino al C++11, se uno o entrambi gli operandi dell’operatore binario % erano negativi, il segno del resto era definito dall’implementazione, poiché dipende dalla direzione di arrotondamento della divisione intera. La funzione std::div forniva un comportamento ben definito in quel caso.

Nota: per il resto in virgola mobile, vedere std::remainder e std::fmod.

Nella risoluzione di sovraccarico contro operatori definiti dall’utente, per ogni coppia di tipi aritmetici promossi LA e RA e per ogni coppia di tipi integrali promossi LI e RI le seguenti firme di funzione partecipano alla risoluzione di sovraccarico:

LRA operator*(LA, RA)

LRA operator/(LA, RA)

LRI operator%(LI, RI)

dove LRx è il risultato delle usuali conversioni aritmetiche su Lx e Rx

Esegui questo codice
#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';}

Output:

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

Operatori logici bitwise

Le espressioni degli operatori aritmetici bitwise hanno la forma

~ rhs (1)
lhs & rhs (2)
lhs | rhs (3)
lhs ^ rhs (4)
1) bitwise NOT
2) bitwise AND
3) bitwise OR
4) bitwise XOR
Per gli operatori built-in operatori, lhs e rhs devono avere entrambi un tipo di enumerazione integrale o nonscoped. Le conversioni aritmetiche usuali sono eseguite su entrambi gli operandi e determinano il tipo del risultato.

Il risultato dell’operatore~ è il valore bitwise NOT (complemento a uno) dell’argomento (dopo la promozione). Il risultato dell’operatore& è il valore bitwise AND degli operandi (dopo le solite conversioni aritmetiche). Il risultato dell’operatore| è il valore OR bitwise degli operandi (dopo le solite conversioni aritmetiche). Il risultato dell’operatore^ è il valore XOR bitwise degli operandi (dopo le usuali conversioni aritmetiche)

Nella risoluzione di sovraccarico contro operatori definiti dall’utente, per ogni coppia di tipi integrali promossi L e R le seguenti firme di funzione partecipano alla risoluzione di sovraccarico:

R operator~(R)

LR operator&(L, R)

LR operator^(L, R)

LR operator|(L, R)

dove LR è il risultato delle usuali conversioni aritmetiche su L e R

Esegui questo codice
#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';}

Output:

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

Operatori bitwise shift

Le espressioni dell’operatore bitwise shift hanno la forma

lhs << rhs (1)
lhs >> rhs (2)
1) spostamento a sinistra di lhs per bit di rhs
2) spostamento a destra di lhs per bit di rhs
Per gli operatori integratiin operatori, lhs e rhs devono avere entrambi un tipo di enumerazione integrale o unscoped. Le promozioni integrali sono eseguite su entrambi gli operandi.

Il tipo di ritorno è il tipo dell’operando sinistro dopo le promozioni integrali.

Per i senza segno a, il valore di a << b è il valore di a * 2b
, ridotto modulo 2N
dove N è il numero di bit nel tipo di ritorno (cioè, viene eseguito lo spostamento a sinistra bitwise e i bit che vengono spostati fuori dal tipo di destinazione vengono scartati).

Per i a firmati e non negativi, se un * 2b
è rappresentabile nella versione senza segno del tipo di ritorno, allora quel valore, convertito in firmato, è il valore di a << b (questo rende legale creare INT_MIN come 1<<31); altrimenti il comportamento è indefinito.

Per i a negativi, il comportamento di a << b non è definito.

Per a senza segno e per a firmato e non negativo, il valore di a >> b è la parte intera di a/2b
.

Per a negativo, il valore di a >> b è definito dall’implementazione (nella maggior parte delle implementazioni, questo esegue lo spostamento aritmetico a destra, in modo che il risultato resti negativo).

(fino a C++20)

Il valore di a << b è l’unico valore congruente ad a * 2b
modulo 2N
dove N è il numero di bit nel tipo di ritorno (cioè, viene eseguito lo spostamento a sinistra bitwise e i bit che vengono spostati fuori dal tipo di destinazione vengono scartati).

Il valore di a >> b è a/2b
, arrotondato per difetto (in altre parole, lo spostamento a destra su a firmato è uno spostamento aritmetico a destra).

(dal C++20)

In ogni caso, se il valore dell’operando destro è negativo o è maggiore o uguale al numero di bit nell’operando sinistro promosso, il comportamento non è definito.

Nella risoluzione di sovraccarico contro operatori definiti dall’utente, per ogni coppia di tipi integrali promossi L e R, le seguenti firme di funzione partecipano alla risoluzione di sovraccarico:

L operator<<(L, R)

L operator>>(L, R)

Esegui questo codice
#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';}

Output:

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

Libreria standard

Gli operatori aritmetici sono sovraccaricati per molti tipi di libreria standard.

Operatori aritmetici unari

implementa unari + e unari –
(funzione membro pubblico di std::chrono::duration<Rep,Period>)

applica operatori unari ai numeri complessi
(template di funzione)

applica un operatore aritmetico unario a ciascun elemento del valarray
(funzione membro pubblico di std::valarray<T>)

Operatori additivi

esegue operazioni di addizione e sottrazione che coinvolgono un punto temporale
(function template)

implementa operazioni aritmetiche con durate come argomenti
(function template)

aggiunge o sottrae un year_month_day e qualche numero di anni o mesi
(funzione membro pubblico di std::chrono::year_month_day)

concatena due stringhe o una stringa e un char
(function template)

fa avanzare o diminuire l’iteratore
(funzione membro pubblico di std::reverse_iterator<Iter>)

avanza o decrementa l’iteratore
(funzione membro pubblico di std::move_iterator<Iter>)

esegue l’aritmetica dei numeri complessi su due valori complessi o un complesso e uno scalare
(modello di funzione)

applica operatori binari a ciascun elemento di due valarray, o un valarray e un valore
(function template)

Operatori moltiplicativi

implementa operazioni aritmetiche con durate come argomenti
(function template)

esegue l’aritmetica dei numeri complessi su due valori complessi o un complesso e uno scalare
(function template)

applica operatori binari a ciascun elemento di due valarray, o un valarray e un valore
(function template)

Gli operatori logici bitwise

eseguono AND, OR, XOR e NOT
(funzione membro pubblico di std::bitset<N>)

esegue operazioni logiche binarie su bitset
(function template)

applica un operatore aritmetico unario ad ogni elemento del valarray
(funzione membro pubblico di std::valarray<T>)

applica operatori binari ad ogni elemento di due valarray, o un valarray e un valore
(modello di funzione)

Operatori di spostamento bitwise

applica operatori binari a ciascun elemento di due valarray, o un valarray e un valore
(function template)

esegue lo shift binario a sinistra e lo shift a destra
(public member function of std::bitset<N>)

Operatori di inserimento/estrazione stream

In tutta la libreria standard, gli operatori bitwise shift sono comunemente sovraccaricati con stream I/O (std::ios_base& o una delle classi da esso derivate) sia come operando sinistro che come tipo di ritorno. Tali operatori sono conosciuti come operatori di inserimento e di estrazione del flusso:

estrae dati formattati
(funzione membro pubblico di std::basic_istream<CharT,Traits>)

estrae caratteri e matrici di caratteri
(modello di funzione)

inserisce dati formattati
(funzione membro pubblico di std::basic_ostream<CharT,Traits>)

inserisce dati caratteri
(modello di funzione)

serializza e deserializza un numero complesso
(function template)

esegue stream input e output di bitset
(function template)

esegue stream input e output su stringhe
(function template)

esegue stream input e output su pseudo-motore di numeri casuali
(function template)

esegue l’input e l’output di stream sulla distribuzione di numeri pseudo-casuali
(function template)

Segnalazioni di difetti

Le seguenti segnalazioni di difetti che modificano il comportamento sono state applicate retroattivamente agli standard C++ precedentemente pubblicati.

DR Applicato a Comportamento come pubblicato Comportamento corretto
CWG 1457 C++98 spostamento del bit più a sinistra 1 di un valore con segno positivo nel bit del segno è stato UB reso bendefinito

Vedi anche

Precedenza degli operatori

Sovraccarico degli operatori

Operatori comuni
assegnazione incremento
decremento
aritmetico logico confronto membro
accesso
altro

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

Operatori speciali

static_cast converte un tipo in un altro tipo correlato
dynamic_cast converte all’interno di gerarchie di eredità
const_cast aggiunge o rimuove i qualificatori cv
reinterpret_cast converte il tipo in un tipo non correlato
C-style cast converte un tipo in un altro con un mix di static_cast, const_cast e reinterpret_cast
new crea oggetti con durata di memorizzazione dinamica
delete destruttura gli oggetti precedentemente creati dall’espressione new e rilascia l’area di memoria ottenuta
sizeof interroga la dimensione di un tipo
sizeof… interroga la dimensione di un pacchetto di parametri (dal C++11)
typeid interroga le informazioni sul tipo di un tipo
noexcept controlla se un’espressione può lanciare un’eccezione (dal C++11)
alignof interroga i requisiti di allineamento di un tipo (dal C++11)

documentazione C per operatori aritmetici

Lascia un commento