Opérateurs arithmétiques

Langage C++

. d’exécution conditionnelle

.

.

Thèmes généraux
Contrôle du flux
Déclarations d’exécution conditionnelles

if

Instructions d’itération (boucles)

for

plage-for (C++11)

Instructions de saut

continuebreak

goto -. return

Fonctions
Déclaration de fonction
Déclaration de fonction lambda
inline spécificateur
Spécifications des exceptions (jusqu’à C++20)
. noexcept spécificateur (C++11)
Exceptions
Espaces de noms
Types
Spécificateurs

decltype (C++11)

auto (C++11)

alignas (C++11)

. const/volatile

constexpr (C++11)

Spécification de la durée de stockage
. Initialisation
.

.

Expressions
Représentations alternatives
Littéraux
Booléen -. Entier – Virgule flottante
Caractère – Chaîne – nullptr (C++11)
Défini par l’utilisateur (C++11)
.définis par l’utilisateur (C++11)
Utilitaires
Attributs (C++11)
Types
. typedef déclaration
Déclaration d’alias de type (C++11)
Casts
Conversions implicites -. Conversions explicites
static_castdynamic_cast
const_castreinterpret_cast
Allocation de mémoire
Classes
Classe-propriétés des fonctions spécifiques

Fonction virtuelle

spécificateur de surcharge (C++11)

spécificateur final (C++11)

. explicit (C++11)

static

Fonctions membres spéciales

Affectation de copie

Affectation de déplacement (C++11).

Destructeur

Modèles

Spécialisation des modèles

Paquets de paramètres (C++11)

Divers
Expressions

Catégories de valeurs générales

(lvalue, rvalue, xvalue)

ordre d’évaluation (points de séquence)

expressions constantes

expressions non évaluées

expressions primaires

expression lambda(C++11)

littéraux

littéraux entiers

littéraux à virgule flottante

littéraux à virgule flottante

.flottante

littéraux booléens

littéraux de caractères, y compris les séquences d’échappement

littéraux de chaînes de caractères

littéral de pointeur nul (C++11)

littéral défini par l’utilisateur (C++11)

opérateurs

opérateurs d’affectation : a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b

Incrémentation et décrémentation : ++a, --a, a++, a--

Opérateurs arithmétiques:+a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b

Opérateurs logiques : a||b, a&&b, !a

Opérateurs de comparaison : a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)

Opérateurs d’accès aux membres : a, *a, &a, a->b, a.b, a->*b, a.*b

Autres opérateurs : a(...), a,b, a?b:c

nouvelle-expression

suppression-expression

lancer-expression

alignof

sizeof

sizeof…(C++11)

typeid

noexcept(C++11)

Expression repliée(C++17)

Représentations alternatives des opérateurs

Préséance et associativité

Surcharge des opérateurs

. Comparaisons par défaut(C++20)

Conversions

Conversions implicites

const_cast

static_cast

reinterpret_cast

dynamic_cast

Conversions explicites (T)a, T(a)

Conversion définie par l’utilisateur

Retourne le résultat d’une opération arithmétique spécifique.

.

Nom de l’opérateur Syntaxe Surchargeable Exemples de prototypes (pour la classe T)
Définition intérieure de la classe Définition extérieure de la classe
unaire plus +a Oui T T ::operator+() const ; T operator+(const T &a) ;
unaire moins -a Yes T ::operator-() const ; T operator-(const T &a) ;
addition a + b Yes T: :operator+(const T2 &b) const ; T operator+(const T &a, const T2 &b) ;
soustraction a - b Yes T T: :operator-(const T2 &b) const ; T operator-(const T &a, const T2 &b) ;
multiplication a * b Yes T ::operator*(const T2 &b) const ; T operator*(const T &a, const T2 &b) ;
division a / b Yes T ::operator/(const T2 &b) const ; T operator/(const T &a, const T2 &b) ;
modulo a % b Yes 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 T: :operator&(const T2 &b) const ; T operator&(const T &a, const T2 &b) ;
OR bitwise a | b Yes T: ::operator|(const T2 &b) const ; T operator|(const T &a, const T2 &b) ;
XOR binaire a ^ b Yes T: :operator^(const T2 &b) const ; T operator^(const T &a, const T2 &b) ;
décalage bit à gauche a << b Yes T: :operator<<(const T2 &b) const ; T operator<<(const T &a, const T2 &b) ;
décalage binaire à droite a >> b Yes T:: ::operator>>(const T2 &b) const ; T operator>>(const T &a, const T2 &b) ;
Notes

  • Tous les opérateurs intégrés renvoient des valeurs, et la plupart des surcharges définies par l’utilisateur renvoient également des valeurs afin que les opérateurs définis par l’utilisateur puissent être utilisés de la même manière que les intégrés. Cependant, dans une surcharge d’opérateur définie par l’utilisateur, tout type peut être utilisé comme type de retour (y compris void). En particulier, les surcharges d’insertion de flux et d’extraction de flux de operator<< et operator>> renvoient T&.
  • T2 peut être de n’importe quel type, y compris T

  • 1 Explication
    • 1.1 Conversions
    • 1.2 Débordements
    • 1.3 Environnement en virgule flottante
    • 1.4 Contraction en virgule flottante
    • 1.5 Opérateurs arithmétiques unaires
    • 1.6 Opérateurs additifs
    • 1.7 Opérateurs multiplicatifs
    • 1.8 Opérateurs logiques bit à bit
    • 1.9 Opérateurs de décalage par bit
  • 2 Bibliothèque standard
    • 2.1 Opérateurs arithmétiques unaires
    • 2.2 Opérateurs additifs
    • 2.3 Opérateurs multiplicatifs
    • 2.4 Opérateurs logiques par bit
    • 2.5 Opérateurs de décalage par bit
    • 2.6 Opérateurs d’insertion/extraction de flux
  • 3 Rapports de défauts
  • 4 Voir aussi

Explication

Tous les opérateurs arithmétiques calculent le résultat d’une opération arithmétique spécifique et renvoient son résultat. Les arguments ne sont pas modifiés.

Conversions

Si l’opérande passé à un opérateur arithmétique est de type intégral ou d’énumération non scopée, alors avant toute autre action (mais après la conversion de lvalue à rvalue, le cas échéant), l’opérande subit une promotion intégrale. Si un opérande a un type tableau ou fonction, les conversions tableau à pointeur et fonction à pointeur sont appliquées.

Pour les opérateurs binaires (sauf les décalages), si les opérandes promus ont des types différents, un ensemble supplémentaire de conversions implicites est appliqué, connu sous le nom de conversions arithmétiques habituelles dans le but de produire le type commun (également accessible via le trait de type std::common_type). Si, avant toute promotion intégrale, un opérande est de type énumération et l’autre opérande est de type flottant ou de type énumération différent, ce comportement est déprécié. (depuis C++20)

  • Si l’un des opérandes est de type énumération scopée, aucune conversion n’est effectuée : l’autre opérande et le type de retour doivent avoir le même type
  • Sinon, si l’un des opérandes est long double, l’autre opérande est converti en long double
  • Sinon, si l’un des opérandes est double, l’autre opérande est converti en double
  • Sinon, si l’un des opérandes est un flottant, l’autre opérande est converti en flottant
  • Sinon, l’opérande a le type entier (parce que bool, char, char8_t, char16_t, char32_t, wchar_t et l’énumération non scopée ont été promus à ce point) et les conversions intégrales sont appliquées pour produire le type commun, comme suit :
  • Si les deux opérandes sont signés ou si les deux sont non signés, l’opérande ayant le rang de conversion le moins élevé est converti en opérande ayant le rang de conversion d’entier le plus élevé
  • Sinon, si le rang de conversion de l’opérande non signé est supérieur ou égal au rang de conversion de l’opérande signé, l’opérande signé est converti en type d’opérande non signé.
  • Sinon, si le type de l’opérande signé peut représenter toutes les valeurs de l’opérande non signé, l’opérande non signé est converti au type de l’opérande signé
  • Sinon, les deux opérandes sont convertis à la contrepartie non signée du type de l’opérande signé.

Le rang de conversion ci-dessus augmente dans l’ordre bool, signed char, short, int, long, long long. Le rang de tout type non signé est égal au rang du type signé correspondant. Le rang de char est égal au rang de char signé et de char non signé. Les rangs de char8_t, char16_t, char32_t, et wchar_t sont égaux aux rangs de leurs types sous-jacents.

Dépassements

L’arithmétique des entiers non signés est toujours effectuée modulo 2n
où n est le nombre de bits dans cet entier particulier. Par exemple, pour unsigned int, ajouter un à UINT_MAX donne 0, et soustraire un de 0 donne UINT_MAX.

Lorsque l’opération arithmétique sur les entiers signés déborde (le résultat ne rentre pas dans le type de résultat), le comportement est indéfini, – les manifestations possibles d’une telle opération incluent :

  • elle s’enroule selon les règles de la représentation (typiquement le complément à 2),
  • elle piège – sur certaines plateformes ou en raison des options du compilateur (par ex.par exemple -ftrapv dans GCC et Clang),
  • il sature à la valeur minimale ou maximale (sur de nombreux DSP),
  • il est complètement optimisé par le compilateur.

Environnement à virgule flottante

Si #pragma STDC FENV_ACCESS est supporté et défini à ON, tous les opérateurs arithmétiques en virgule flottante obéissent au sens d’arrondi actuel en virgule flottante et signalent les erreurs arithmétiques en virgule flottante comme spécifié dans math_errhandling, sauf s’ils font partie d’un initialisateur statique (auquel cas les exceptions en virgule flottante ne sont pas levées et le mode d’arrondi est au plus proche)

Contraction en virgule flottante

Sauf si #pragma STDC FP_CONTRACT est supporté et défini à OFF, toute l’arithmétique en virgule flottante peut être effectuée comme si les résultats intermédiaires avaient une portée et une précision infinies, c’est-à-dire que les optimisations qui omettent les erreurs d’arrondi et les exceptions en virgule flottante sont autorisées. Par exemple, C++ permet la mise en œuvre de (x*y) + z avec une seule instruction CPU de multiplication-addition fusionnée ou l’optimisation de a = x*x*x*x ; comme tmp = x *x ; a = tmp*tmp.

Sans rapport avec la contractualisation, les résultats intermédiaires de l’arithmétique à virgule flottante peuvent avoir une plage et une précision différentes de celles indiquées par son type, voir FLT_EVAL_METHOD

Formellement, la norme C++ ne donne aucune garantie sur la précision des opérations à virgule flottante.

Opérateurs arithmétiques unaires

Les expressions des opérateurs arithmétiques unaires ont la forme

+ expression . (1)
- expression (2)
1) unaire plus (promotion).
Pour l’opérateur intégré, l’expression doit être de type arithmétique, énumération non scopée ou pointeur. La promotion intégrale est effectuée sur l’opérande s’il a le type intégral ou d’énumération non scopée et détermine le type du résultat.
2) unaire moins (négation).
Pour l’opérateur intégré, l’expression doit avoir le type arithmétique ou d’énumération non scopée. La promotion intégrale est effectuée sur l’opérande et détermine le type du résultat.

L’opérateur intégré unaire plus retourne la valeur de son opérande. La seule situation où il n’est pas un no-op est lorsque l’opérande a un type intégral ou un type d’énumération non scopé, qui est modifié par la promotion intégrale, par exemple, il convertit char en int ou si l’opérande est soumis à une conversion lvalue-to-rvalue, array-to-pointer, ou function-to-pointer.

L’opérateur unaire moins intégré calcule le négatif de son opérande promu. Pour un non signé a, la valeur de -a est 2b
-a, où b est le nombre de bits après promotion.

Dans la résolution de surcharge contre les opérateurs définis par l’utilisateur, pour chaque type arithmétique promu A et pour chaque type T, les signatures de fonctions suivantes participent à la résolution de surcharge :

A operator+(A)

T* operator+(T*)

A operator-(A)

Exécuter ce code
#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';}

Sortie :

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

Opérateurs additifs

Les expressions des opérateurs arithmétiques additifs binaires ont la forme

lhs + rhs. (1)
lhs - rhs (2)
1) addition
Pour l’opérateur incorporédans l’opérateur, lhs et rhs doivent être l’un des suivants :

  • les deux ont un type arithmétique ou d’énumération non scopé. Dans ce cas, les conversions arithmétiques habituelles sont effectuées sur les deux opérandes et déterminent le type du résultat.
  • l’un est un pointeur vers un type d’objet complètement défini, l’autre a un type intégral ou d’énumération non scopé. Dans ce cas, le type du résultat a le type du pointeur.
2) soustraction
Pour l’opérateur intégré, lhs et rhs doivent être l’un des suivants :

  • les deux ont un type arithmétique ou d’énumération non scopé. Dans ce cas, les conversions arithmétiques habituelles sont effectuées sur les deux opérandes et déterminent le type du résultat.
  • lhs est un pointeur vers un type d’objet complètement défini, rhs a un type intégral ou d’énumération non scopé. Dans ce cas, le type du résultat a le type du pointeur.
  • les deux sont des pointeurs vers les mêmes types d’objets complètement définis, en ignorant les cv-qualificateurs. Dans ce cas, le type du résultat est std::ptrdiff_t.

Avec des opérandes de type arithmétique ou énumération, le résultat de l’opérateur binaire plus est la somme des opérandes (après les conversions arithmétiques habituelles), et le résultat de l’opérateur binaire moins est le résultat de la soustraction du second opérande du premier (après les conversions arithmétiques habituelles), sauf que, si le type supporte l’arithmétique à virgule flottante IEEE (voir std::numeric_limits: :is_iec559),

  • si un opérande est NaN, le résultat est NaN
  • l’infini moins l’infini est NaN et FE_INVALID est élevé
  • l’infini plus l’infini négatif est NaN et FE_INVALID est élevé

Si l’un des opérandes est un pointeur, les règles suivantes s’appliquent :

  • Un pointeur sur un objet hors tableau est traité comme un pointeur sur le premier élément d’un tableau de taille 1.
  • Si le pointeur P pointe vers le ie élément d’un tableau, alors les expressions P+n, n+P et P-n sont des pointeurs du même type qui pointent vers le i+ne, i+ne et i-ne élément du même tableau, respectivement. Le résultat de l’addition des pointeurs peut également être un pointeur un-passé de la fin (c’est-à-dire le pointeur P tel que l’expression P-1 pointe sur le dernier élément du tableau). Toute autre situation (c’est-à-dire les tentatives de générer un pointeur qui ne pointe pas sur un élément du même tableau ou un élément passé à la fin) invoque un comportement non défini.
  • Si le pointeur P pointe sur le ie élément d’un tableau, et le pointeur Q pointe sur le je élément du même tableau, l’expression P-Q a la valeur i-j, si la valeur tient dans std::ptrdiff_t. Les deux opérandes doivent pointer sur les éléments du même tableau (ou un élément au-delà de la fin), sinon le comportement est indéfini. Si le résultat ne tient pas dans std::ptrdiff_t, le comportement est indéfini.
  • Dans tous les cas, si le type pointé est différent du type de l’élément du tableau, sans tenir compte des qualifications cv, à chaque niveau si les éléments sont eux-mêmes des pointeurs, le comportement de l’arithmétique des pointeurs est indéfini. En particulier, l’arithmétique de pointeur avec pointeur sur base, qui pointe sur un élément d’un tableau d’objets dérivés est indéfinie.
  • Si la valeur 0 est ajoutée ou soustraite d’un pointeur, le résultat est le pointeur, inchangé. Si deux pointeurs pointent sur le même objet ou sont tous deux à un passé de la fin du même tableau, ou sont tous deux des pointeurs nuls, alors le résultat de la soustraction est égal à (std::ptrdiff_t)0.

Ces opérateurs arithmétiques de pointeurs permettent aux pointeurs de satisfaire aux exigences de LegacyRandomAccessIterator.

Dans la résolution de surcharge contre les opérateurs définis par l’utilisateur, pour chaque paire de types arithmétiques promus L et R et pour chaque type d’objet T, les signatures de fonctions suivantes participent à la résolution de surcharge :

LR opérateur+(L, R)

LR opérateur-(L, R)

T* opérateur+(T*, std: :ptrdiff_t)

T* operator+(std: :ptrdiff_t, T*)

T* operator-(T*, std::ptrdiff_t)

std: :ptrdiff_t operator-(T*, T*)

LR est le résultat des habituelles conversions arithmétiques sur L et R

Exécutez ce code
#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';}

Sortie :

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

Opérateurs multiplicatifs

Les expressions des opérateurs arithmétiques multiplicatifs binaires ont la forme

.

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
1) multiplication
Pour l’opérateur incorporédans l’opérateur, lhs et rhs doivent tous deux avoir un type arithmétique ou d’énumération non scopé.
2) division
Pour l’opérateur incorporé, lhs et rhs doivent tous deux avoir le type arithmétique ou d’énumération non scopée.
3) reste
Pour l’opérateur intégré, lhs et rhs doivent tous deux avoir un type d’énumération intégral ou non scopé

Pour ces trois opérateurs, les conversions arithmétiques habituelles sont effectuées sur les deux opérandes et déterminent le type du résultat.

L’opérateur binaire * effectue la multiplication de ses opérandes (après les conversions arithmétiques habituelles), sauf que, pour la multiplication en virgule flottante,

  • la multiplication d’un NaN par un nombre quelconque donne NaN
  • la multiplication de l’infini par zéro donne NaN et FE_INVALID est soulevé

L’opérateur binaire / divise le premier opérande par le second (après les conversions arithmétiques habituelles).

Pour les opérandes entiers, il donne le quotient algébrique.

Le quotient est arrondi dans la direction définie par l’implémentation.

(jusqu’à C++11)

Le quotient est tronqué vers zéro (la partie fractionnaire est rejetée).

(depuis C++11)

Si le second opérande est zéro, le comportement est indéfini, sauf que si une division en virgule flottante a lieu et que le type supporte l’arithmétique en virgule flottante IEEE (voir std ::numeric_limits::is_iec559), alors:

  • si un opérande est NaN, le résultat est NaN
  • divisant un nombre non nul par ±0.0 donne l’infini correctement signé et FE_DIVBYZERO est soulevé
  • diviser 0,0 par 0,0 donne NaN et FE_INVALID est soulevé

L’opérateur binaire % donne le reste de la division entière du premier opérande par le second (après les conversions arithmétiques habituelles ; notez que les types d’opérande doivent être des types entiers). Si le quotient a/b est représentable dans le type de résultat, (a/b)*b + a%b == a. Si le second opérande est zéro, le comportement est indéfini. Si le quotient a/b n’est pas représentable dans le type de résultat, le comportement de a/b et de a%b est indéfini (cela signifie que INT_MIN%-1 est indéfini sur les systèmes de complément à 2)

Note : Jusqu’à C++11, si l’un ou les deux opérandes de l’opérateur binaire % étaient négatifs, le signe du reste était défini par l’implémentation, car il dépend de la direction d’arrondi de la division des entiers. La fonction std::div fournissait un comportement bien défini dans ce cas.

Note : pour le reste en virgule flottante, voir std::remainder et std::fmod.

Dans la résolution de surcharge contre les opérateurs définis par l’utilisateur, pour chaque paire de types arithmétiques promus LA et RA et pour chaque paire de types intégraux promus LI et RI, les signatures de fonctions suivantes participent à la résolution de surcharge :

LRA operator*(LA, RA)

LRA operator/(LA, RA)

LRI operator%(LI, RI)

LRx est le résultat des conversions arithmétiques habituelles sur LRx. conversions arithmétiques sur Lx et Rx

Exécutez ce code
#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';}

Sortie :

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

Opérateurs logiques bit à bit

Les expressions des opérateurs arithmétiques bit à bit ont la forme

.

.

.

~ rhs (1)
lhs & rhs (2)
lhs | rhs (3)
lhs ^ rhs (4)
1) NOT
au sens du bit 2) AND
au sens du bit 3) OR
au sens du bit 4) XOR
au sens du bit Pour les opérateurs incorporésdans les opérateurs intégrés, lhs et rhs doivent tous deux être de type intégral ou d’énumération non scopée. Les conversions arithmétiques habituelles sont effectuées sur les deux opérandes et déterminent le type du résultat.

Le résultat de l’opérateur~ est la valeur NOT au sens du bit (complément à un) de l’argument (après promotion). Le résultat de l’opérateur& est la valeur ET au sens du bit des opérandes (après les conversions arithmétiques habituelles). Le résultat de l’opérateur| est la valeur OU au niveau du bit des opérandes (après les conversions arithmétiques habituelles). Le résultat de l’opérateur^ est la valeur XOR au sens du bit des opérandes (après les conversions arithmétiques habituelles)

Dans la résolution de surcharge contre les opérateurs définis par l’utilisateur, pour chaque paire de types intégraux promus L et R, les signatures de fonctions suivantes participent à la résolution de surcharge :

R operator~(R)

LR operator&(L, R)

LR opérateur^(L, R)

LR opérateur|(L, R)

LR est le résultat des conversions arithmétiques habituelles sur LR. conversions arithmétiques sur L et R

Exécutez ce code
#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';}

Sortie :

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

Opérateurs de décalage bit à bit

Les expressions des opérateurs de décalage bit à bit ont la forme

.

lhs << rhs (1)
lhs >> rhs (2)
1) décalage à gauche de lhs par rhs bits
2) décalage à droite de lhs par rhs bits
Pour les opérateurs incorporésdans les opérateurs, lhs et rhs doivent tous deux être de type intégral ou de type énumération non scopée. Les promotions intégrales sont effectuées sur les deux opérandes.

Le type de retour est le type de l’opérande de gauche après les promotions intégrales.

Pour les non signés a, la valeur de a << b est la valeur de a * 2b
, réduite modulo 2N
où N est le nombre de bits dans le type de retour (c’est-à-dire qu’un décalage à gauche par bit est effectué et les bits qui sont décalés hors du type de destination sont rejetés).

Pour les a signés et non négatifs, si une * 2b
est représentable dans la version non signée du type de retour, alors cette valeur, convertie en signée, est la valeur de a << b (cela rend légal de créer INT_MIN comme 1<<31) ; sinon le comportement est indéfini.

Pour les a négatifs, le comportement de a << b est indéfini.

Pour les a non signés et pour les a signés et non négatifs, la valeur de a >> b est la partie entière de a/2b
.

Pour les a négatifs, la valeur de a >> b est définie par l’implémentation (dans la plupart des implémentations, cela effectue un décalage arithmétique vers la droite, de sorte que le résultat reste négatif).

(jusqu’à C++20)

La valeur de a << b est la valeur unique congruente à a * 2b
modulo 2N
où N est le nombre de bits dans le type de retour (c’est-à-dire que le décalage à gauche par bit est effectué et les bits qui sont décalés hors du type de destination sont rejetés).

La valeur de a >> b est a/2b
, arrondie vers le bas (en d’autres termes, le décalage à droite sur a signé est un décalage arithmétique à droite).

(depuis C++20)

Dans tous les cas, si la valeur de l’opérande de droite est négative ou est supérieure ou égale au nombre de bits de l’opérande de gauche promu, le comportement est indéfini.

Dans la résolution de surcharge contre les opérateurs définis par l’utilisateur, pour chaque paire de types intégraux promus L et R, les signatures de fonctions suivantes participent à la résolution de surcharge :

L opérateur<<(L, R)

L opérateur>>(L, R)

Exécuter ce code
#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';}

Sortie :

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

Bibliothèque standard

Les opérateurs arithmétiques sont surchargés pour de nombreux types de la bibliothèque standard.

Opérateurs arithmétiques unaires

met en œuvre le + unaire et le – unaire.
(fonction publique membre de std::chrono::duration<Rep,Period>)

applique les opérateurs unaires aux nombres complexes
(modèle de fonction)

applique un opérateur arithmétique unaire à chaque élément du tableau de valeurs
(fonction publique membre de std::valarray<T>)

. Opérateurs additifs

effectue des opérations d’addition et de soustraction impliquant un point temporel
(modèle de fonction)

met en œuvre des opérations arithmétiques avec des durées comme arguments
(modèle de fonction)

ajoute ou soustrait un year_month_day et un certain… nombre d’années ou de mois
(fonction publique membre de std::chrono::year_month_day)

concatène deux chaînes ou une chaîne et un char
(modèle de fonction)

avance ou diminue l’itérateur
(fonction publique membre de std::reverse_iterator<Iter>)

. avance ou diminue l’itérateur
(fonction publique membre de std::move_iterator<Iter>)

effectue l’arithmétique des nombres complexes sur deux valeurs complexes ou un complexe et un scalaire
(modèle de fonction)

applique des opérateurs binaires à chaque élément de deux tableaux de valeurs, ou un tableau de valeurs et une valeur
(modèle de fonction)

Opérateurs multiplicatifs

met en œuvre des opérations arithmétiques avec des durées comme arguments
(modèle de fonction).

effectue des opérations arithmétiques sur deux valeurs complexes ou sur un complexe et un scalaire
(function template)

applique des opérateurs binaires à chaque élément de deux valarrays, ou un tableau de valeurs et une valeur
(modèle de fonction)

Opérateurs logiques de type bitwise

effectue des opérations binaires AND, OR, XOR et NOT
(fonction membre public de std::bitset<N>)

effectue des opérations logiques binaires sur des ensembles de bits
(modèle de fonction)

applique un opérateur arithmétique unaire à chaque élément du tableau de valeurs
(fonction membre public de std::valarray<T>)

applique des opérateurs binaires à chaque élément de deux tableaux de valeurs, ou un tableau de valeurs et une valeur
(modèle de fonction)

Opérateurs de décalage binaire

applique des opérateurs binaires à chaque élément de deux tableaux de valeurs, ou un tableau de valeurs et une valeur
(modèle de fonction)

effectue un décalage binaire vers la gauche et vers la droite
(fonction membre publique de std::bitset<N>)

Opérateurs d’insertion/extraction de flux

Dans toute la bibliothèque standard, les opérateurs de décalage binaire sont couramment surchargés avec le flux d’E/S (std ::ios_base& ou l’une des classes qui en sont dérivées) à la fois comme opérande gauche et comme type de retour. De tels opérateurs sont connus sous le nom d’opérateurs d’insertion de flux et d’extraction de flux :

extrait des données formatées
(fonction membre public de std::basic_istream<CharT,Traits>)

extrait des caractères et des tableaux de caractères
(modèle de fonction)

insère des données formatées
(fonction membre public de std::basic_ostream<CharT,Traits>)

insère des données de caractères
(modèle de fonction)

.

sérialise et désérialise un nombre complexe
(modèle de fonction)

effectue une entrée et une sortie de flux de bitsets
(modèle de fonction)

effectue une entrée et une sortie de flux sur des chaînes
(modèle de fonction)

effectue une entrée et une sortie de flux sur un moteur de nombres pseudo-aléatoires.moteur de nombres aléatoires
(modèle de fonction)

effectue l’entrée et la sortie de flux sur la distribution de nombres pseudo-aléatoires
(modèle de fonction)

Rapports de défauts

Les rapports de défauts suivants, qui modifient le comportement, ont été appliqués rétroactivement aux normes C++ publiées précédemment.

DR Appliqué à Comportement tel que publié Comportement correct
CWG 1457 C++98 Le décalage du bit 1 le plus à gauche d’une valeur signée positive dans le bit de signe a été UB rendu bien…défini

Voir aussi

Précédence des opérateurs

Surcharge des opérateurs

Opérateurs communs
affectation . incrémentation
décrémentation
arithmétique logique comparaison membre
accès
autre

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

Opérateurs spéciaux

static_cast convertit un type en un autre type apparenté
dynamic_cast convertit au sein des hiérarchies d’héritage
const_cast ajoute ou supprime les qualificatifs cv
reinterpret_cast convertit un type en un type non apparenté
C-style cast convertit un type en un autre par un mélange de static_cast, const_cast, et reinterpret_cast
new crée des objets avec une durée de stockage dynamique
delete détruit les objets précédemment créés par l’expression new et libère la zone mémoire obtenue
sizeof interroge la taille d’un type
sizeof… interroge la taille d’un paquet de paramètres (depuis C++11)
typeid interroge les informations de type d’un type
noexcept vérifie si une expression peut lancer une exception (depuis C++11)
alignof interroge les exigences d’alignement d’un type (depuis C++11)

Documentation C pour les opérateurs arithmétiques

.

Laisser un commentaire