Opérateurs en C et C++ - Operators in C and C++

Il s'agit d'une liste d' opérateurs dans les langages de programmation C et C++ . Tous les opérateurs répertoriés existent en C++ ; la colonne "Inclus dans C", indique si un opérateur est également présent dans C. Notez que C ne prend pas en charge la surcharge d'opérateur .

Lorsqu'il n'est pas surchargé, pour les opérateurs &&, ||, et ,(l' opérateur virgule ), il y a un point de séquence après l'évaluation du premier opérande.

C ++ contient également la conversion de type opérateurs const_cast, static_cast, dynamic_castet reinterpret_cast. Le formatage de ces opérateurs signifie que leur niveau de priorité est sans importance.

La plupart des opérateurs disponibles en C et C++ sont également disponibles dans d'autres langages de la famille C tels que C# , D , Java , Perl et PHP avec la même priorité, associativité et sémantique.

Table

Pour les besoins de ces tableaux, a, b, et creprésentent des valeurs valides (littéraux, valeurs de variables ou valeur de retour), des noms d'objet ou des lvalues, selon le cas. R, Set Treprésente n'importe quel(s) type(s) et Kpour un type de classe ou un type énuméré.

Opérateurs arithmétiques

Tous les opérateurs arithmétiques existent en C et C++ et peuvent être surchargés en C++.

Nom de l'opérateur Syntaxe Exemples de prototypes C++
En tant que membre de K En dehors des définitions de classe
Une addition a + b R K::operator +(S b); R operator +(K a, S b);
Soustraction a - b R K::operator -(S b); R operator -(K a, S b);
Unaire plus ( promotion entière ) +a R K::operator +(); R operator +(K a);
Unaire moins ( additif inverse ) -a R K::operator -(); R operator -(K a);
Multiplication a * b R K::operator *(S b); R operator *(K a, S b);
Division a / b R K::operator /(S b); R operator /(K a, S b);
Modulo (reste entier) a % b R K::operator %(S b); R operator %(K a, S b);
Incrément Préfixe ++a R& K::operator ++(); R& operator ++(K& a);
suffixe a++ R K::operator ++(int); R operator ++(K& a, int);
Remarque : C++ utilise le paramètre dummy sans nom pour différencier les opérateurs d'incrémentation préfixe et suffixe. int
Décrémenter Préfixe --a R& K::operator --(); R& operator --(K& a);
suffixe a-- R K::operator --(int); R operator --(K& a, int);
Remarque : C++ utilise le paramètre dummy sans nom pour différencier les opérateurs de décrémentation de préfixe et de suffixe. int

Opérateurs de comparaison/opérateurs relationnels

Tous les opérateurs de comparaison peuvent être surchargés en C++.

Nom de l'opérateur Syntaxe Inclus
dans C
Exemples de prototypes
En tant que membre de K En dehors des définitions de classe
Égal à a == b Oui bool K::operator ==(S const& b) const; bool operator ==(K const& a, S const& b);
Pas égal à a != b
a not_eq b
Oui bool K::operator !=(S const& b) const; bool operator !=(K const& a, S const& b);
Plus grand que a > b Oui bool K::operator >(S const& b) const; bool operator >(K const& a, S const& b);
Moins que a < b Oui bool K::operator <(S const& b) const; bool operator <(K const& a, S const& b);
Plus grand ou égal à a >= b Oui bool K::operator >=(S const& b) const; bool operator >=(K const& a, S const& b);
Inférieur ou égal à a <= b Oui bool K::operator <=(S const& b) const; bool operator <=(K const& a, S const& b);
Comparaison à trois a <=> b Non auto K::operator <=>(const S &b); auto operator <=>(const K &a, const S &b);
L'opérateur a un total de 3 types de retour possibles : std::weak_ordering, std::strong_orderinget std::partial_orderingvers lesquels ils sont tous convertibles.

Opérateurs logiques

Tous les opérateurs logiques existent en C et C++ et peuvent être surchargés en C++, bien que la surcharge du ET logique et du OU logique soit déconseillée, car en tant qu'opérateurs surchargés, ils se comportent comme des appels de fonction ordinaires, ce qui signifie que leurs deux opérandes sont évalués, donc ils perdent leur propriété d' évaluation de court-circuit bien utilisée et attendue .

Nom de l'opérateur Syntaxe Exemples de prototypes C++
En tant que membre de K En dehors des définitions de classe
Négation logique (PAS) !a
not a
bool K::operator !(); bool operator !(K a);
ET logique a && b a and b bool K::operator &&(S b); bool operator &&(K a, S b);
OU logique a || b
a or b
bool K::operator ||(S b); bool operator ||(K a, S b);

Opérateurs au niveau du bit

Tous les opérateurs au niveau du bit existent en C et C++ et peuvent être surchargés en C++.

Nom de l'opérateur Syntaxe Exemples de prototypes
En tant que membre de K En dehors des définitions de classe
PAS au niveau du bit ~a
compl a
R K::operator ~(); R operator ~(K a);
ET au niveau du bit a & b
a bitand b
R K::operator &(S b); R operator &(K a, S b);
OU au niveau du bit a | b
a bitor b
R K::operator |(S b); R operator |(K a, S b);
XOR au niveau du bit a ^ b
a xor b
R K::operator ^(S b); R operator ^(K a, S b);
Décalage à gauche au niveau du bit a << b R K::operator <<(S b); R operator <<(K a, S b);
Décalage à droite au niveau du bit a >> b R K::operator >>(S b); R operator >>(K a, S b);

Opérateurs d'affectation

Toutes les expressions d'affectation existent en C et C++ et peuvent être surchargées en C++.

Pour les opérateurs donnés, la sémantique de l'expression d'affectation combinée intégrée a ⊚= best équivalente à a = a ⊚ b, sauf qu'elle an'est évaluée qu'une seule fois.

Nom de l'opérateur Syntaxe Exemples de prototypes C++
En tant que membre de K En dehors des définitions de classe
Affectation directe a = b R& K::operator =(S b); N / A
Affectation d'ajout a += b R& K::operator +=(S b); R& operator +=(K& a, S b);
Affectation de soustraction a -= b R& K::operator -=(S b); R& operator -=(K& a, S b);
Affectation de multiplication a *= b R& K::operator *=(S b); R& operator *=(K& a, S b);
Affectation divisionnaire a /= b R& K::operator /=(S b); R& operator /=(K& a, S b);
Affectation modulo a %= b R& K::operator %=(S b); R& operator %=(K& a, S b);
Affectation ET au niveau du bit a &= b
a and_eq b
R& K::operator &=(S b); R& operator &=(K& a, S b);
Affectation OR au niveau du bit a |= b
a or_eq b
R& K::operator |=(S b); R& operator |=(K& a, S b);
Affectation XOR au niveau du bit a ^= b
a xor_eq b
R& K::operator ^=(S b); R& operator ^=(K& a, S b);
Affectation de décalage à gauche au niveau du bit a <<= b R& K::operator <<=(S b); R& operator <<=(K& a, S b);
Affectation de décalage à droite au niveau du bit a >>= b R& K::operator >>=(S b); R& operator >>=(K& a, S b);

Opérateurs membres et pointeurs

Nom de l'opérateur Syntaxe Peut surcharger en C++ Inclus
dans C
Exemples de prototypes C++
En tant que membre de K En dehors des définitions de classe
Indice a[b] Oui Oui R& K::operator [](S b);
N / A
Indirection ("objet pointé par un ") *a Oui Oui R& K::operator *(); R& operator *(K a);
Adresse-de ("adresse d' un ") &a Oui Oui R* K::operator &(); R* operator &(K a);
Déréférencement de structure ("membre b de l'objet pointé par a ") a->b Oui Oui R* K::operator ->();
N / A
Référence de structure ("membre b de l'objet a ") a.b Non Oui N / A
Membre sélectionné par le pointeur vers le membre b de l'objet pointé par un a->*b Oui Non R& K::operator ->*(S b); R& operator ->*(K a, S b);
Membre de l'objet a sélectionné par pointeur sur membre b a.*b Non Non N / A

Autres opérateurs

Nom de l'opérateur Syntaxe Peut surcharger en C++ Inclus
dans C
Exemples de prototypes
En tant que membre de K En dehors des définitions de classe
Appel de fonction
Voir Objet fonction .
a(a1, a2) Oui Oui R K::operator ()(S a, T b, ...); N / A
Virgule a, b Oui Oui R K::operator ,(S b); R operator ,(K a, S b);
Ternaire conditionnel a ? b : c Non Oui N / A
Résolution de la portée a::b Non Non N / A
Littéraux définis par l'utilisateur
depuis C++11
"a"_b Oui Non N / A R operator "" _b(T a)
Taille de sizeof(a)
sizeof(type)
Non Oui N / A
Taille du pack de paramètres
depuis C++11
sizeof...(Args) Non Non N / A
Alignof
depuis C++11
alignof(type)
ou _Alignof(type)
Non Oui N / A
Identification du type typeid(a)
typeid(type)
Non Non N / A
Conversion (fonte de style C) (type)a Oui Oui K::operator R(); N / A
Conversion type(a) Non Non Remarque : se comporte comme const_cast/static_cast/reinterpret_cast
conversion statique_cast static_cast<type>(a) Oui Non K::operator R();
explicit K::operator R(); depuis C++11
N / A
Remarque : pour les conversions définies par l'utilisateur, le type de retour correspond implicitement et nécessairement au nom de l'opérateur.
conversion de distribution dynamique dynamic_cast<type>(a) Non Non N / A
conversion const_cast const_cast<type>(a) Non Non N / A
conversion reinterpret_cast reinterpret_cast<type>(a) Non Non N / A
Allouer du stockage new type Oui Non void* K::operator new(size_t x); void* operator new(size_t x);
Allouer le stockage (tableau) new type[n] Oui Non void* K::operator new[](size_t a); void* operator new[](size_t a);
Désallouer le stockage delete a Oui Non void K::operator delete(void* a); void operator delete(void* a);
Désallouer le stockage (tableau) delete[] a Oui Non void K::operator delete[](void* a); void operator delete[](void* a);
Vérification des exceptions
depuis C++11
noexcept(a) Non Non N / A

Remarques:

Priorité de l'opérateur

Ce qui suit est un tableau qui répertorie la priorité et l' associativité de tous les opérateurs dans les langages C et C++ (lorsque les opérateurs existent également en Java , Perl , PHP et de nombreux autres langages récents, la priorité est la même que celle donnée). Les opérateurs sont répertoriés de haut en bas, par ordre décroissant. La priorité décroissante fait référence à la priorité du regroupement d'opérateurs et d'opérandes. Considérant une expression, un opérateur qui est répertorié sur une ligne sera groupé avant tout opérateur qui est répertorié sur une ligne plus loin en dessous. Les opérateurs qui se trouvent dans la même cellule (il peut y avoir plusieurs rangées d'opérateurs répertoriés dans une cellule) sont regroupés avec la même priorité, dans la direction donnée. La priorité d'un opérateur n'est pas affectée par la surcharge.

La syntaxe des expressions en C et C++ est spécifiée par une grammaire de structure de phrase . Le tableau donné ici a été déduit de la grammaire. Pour la norme ISO C 1999, la section 6.5.6 note 71 indique que la grammaire C fournie par la spécification définit la priorité des opérateurs C, et indique également que la priorité des opérateurs résultant de la grammaire suit étroitement l'ordre des sections de la spécification :

" La syntaxe [C] [c'est-à-dire la grammaire] spécifie la priorité des opérateurs dans l'évaluation d'une expression, qui est la même que l'ordre des principaux paragraphes de ce paragraphe, la priorité la plus élevée en premier."

Une table de priorité, bien que généralement adéquate, ne peut pas résoudre quelques détails. En particulier, notez que l' opérateur ternaire autorise toute expression arbitraire comme opérande intermédiaire, bien qu'il soit répertorié comme ayant une priorité plus élevée que les opérateurs d'affectation et de virgule. Ainsi a ? b, c : dest interprété comme a ? (b, c) : d, et non comme insignifiant (a ? b), (c : d). Ainsi, l'expression au milieu de l'opérateur conditionnel (entre ?et :) est analysée comme si elle était entre parenthèses. Notez également que le résultat immédiat sans parenthèses d'une expression de transtypage C ne peut pas être l'opérande de sizeof. Par conséquent, sizeof (int) * xest interprété comme (sizeof(int)) * xet non sizeof ((int) * x).

Priorité Opérateur La description L'associativité
1

plus haut

:: Résolution de la portée (C++ uniquement) Rien
2 ++ Incrément de suffixe De gauche à droite
-- Décrément de suffixe
() Appel de fonction
[] Abonnement de tableau
. Sélection d'éléments par référence
-> Sélection d'éléments par pointeur
typeid() Informations sur le type d' exécution (C++ uniquement) (voir typeid )
const_cast Type cast (C++ uniquement) (voir const_cast )
dynamic_cast Cast de type (C++ uniquement) (voir cast dynamique )
reinterpret_cast Type cast (C++ uniquement) (voir reinterpret_cast )
static_cast Type cast (C++ uniquement) (voir static_cast )
3 ++ Incrément de préfixe De droite à gauche
-- Décrément de préfixe
+ Unaire plus
- Unaire moins
! NON logique
~ PAS au niveau du bit (complément à un)
(type) Type de fonte
* Indirection (déréférencement)
& Adresse de
sizeof Taille de
_Alignof Exigence d'alignement (depuis C11)
new, new[] Allocation dynamique de mémoire (C++ uniquement)
delete, delete[] Désallocation dynamique de mémoire (C++ uniquement)
4 .* Pointeur vers le membre (C++ uniquement) De gauche à droite
->* Pointeur vers le membre (C++ uniquement)
5 * Multiplication De gauche à droite
/ Division
% Modulo (reste)
6 + Une addition De gauche à droite
- Soustraction
7 << Décalage à gauche au niveau du bit De gauche à droite
>> Décalage à droite au niveau du bit
8 <=> Comparaison à trois (Introduit dans C++20 - C++ uniquement) De gauche à droite
9 < Moins que De gauche à droite
<= Inférieur ou égal à
> Plus grand que
>= Plus grand ou égal à
dix == Égal à De gauche à droite
!= Pas égal à
11 & ET au niveau du bit De gauche à droite
12 ^ Bitwise XOR (exclusif ou) De gauche à droite
13 | OU au niveau du bit (ou inclus) De gauche à droite
14 && ET logique De gauche à droite
15 || OU logique De gauche à droite
16 ?: Ternaire conditionnel (voir ?: ) De droite à gauche
= Affectation directe
+= Affectation par somme
-= Affectation par différence
*= Affectation par produit
/= Affectation par quotient
%= Affectation par reliquat
<<= Affectation par décalage à gauche au niveau du bit
>>= Affectation par décalage à droite au niveau du bit
&= Affectation par ET au niveau du bit
^= Affectation par bit à bit XOR
|= Affectation par OU au niveau du bit
throw Opérateur Throw (lancement d'exceptions, C++ uniquement)
17

le plus bas

, Virgule De gauche à droite

Remarques

La table de priorité détermine l'ordre de liaison dans les expressions chaînées, lorsqu'il n'est pas expressément spécifié par des parenthèses.

  • Par exemple, ++x*3est ambigu sans règle(s) de priorité. La table de précédence nous dit que : x est « lié » plus étroitement à ++ qu'à * , de sorte que tout ce que ++ fait (maintenant ou plus tard—voir ci-dessous), il le fait UNIQUEMENT à x (et non à x*3) ; il est équivalent à ( ++x, x*3).
  • De même, avec 3*x++, où bien que le post-fix ++ soit conçu pour agir APRÈS que l'expression entière ait été évaluée, la table de priorité indique clairement que SEUL x est incrémenté (et PAS 3*x). En fait, l'expression ( tmp=x++, 3*tmp) est évaluée avec tmp étant une valeur temporaire. Il est fonctionnellement équivalent à quelque chose comme ( tmp=3*x, ++x, tmp).
Priorité et liaisons
  • En faisant abstraction de la question de préséance ou de liaison, considérons le diagramme ci-dessus pour l'expression 3+2*y[i]++. Le travail du compilateur consiste à résoudre le diagramme en une expression, dans laquelle plusieurs opérateurs unaires (appelez-les 3+( . ), 2*( . ), ( . )++ et ( . )[ i ]) sont en compétition pour lier jouet. L'ordre de priorité du tableau résout la sous-expression finale sur laquelle chacun agit : ( . )[ i ] agit uniquement sur y, ( . )++ agit uniquement sur y[i], 2*( . ) agit uniquement sur y[ i]++ et 3+( . ) agit 'seulement' sur 2*((y[i])++). Il est important de noter que la sous-expression sur laquelle chaque opérateur agit est claire dans la table de précédence, mais QUAND chaque opérateur agit n'est pas résolu par la table de précédence ; dans cet exemple, l'opérateur ( . )++ agit uniquement sur y[i] par les règles de précédence mais les niveaux de liaison à eux seuls n'indiquent pas le timing du suffixe ++ (l'opérateur ( . )++ n'agit qu'après y[i ] est évalué dans l'expression).

De nombreux opérateurs contenant des séquences de plusieurs caractères reçoivent des "noms" construits à partir du nom d'opérateur de chaque caractère. Par exemple, +=et -=sont souvent appelés plus égal(s) et moins égal(s) , au lieu des plus verbeux « affectation par addition » et « affectation par soustraction ». La liaison des opérateurs en C et C++ est spécifiée (dans les normes correspondantes) par une grammaire de langage factorisée, plutôt que par une table de précédence. Cela crée des conflits subtils. Par exemple, en C, la syntaxe d'une expression conditionnelle est :

logical-OR-expression ? expression : conditional-expression

alors qu'en C++ c'est :

logical-OR-expression ? expression : assignment-expression

D'où l'expression :

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

est analysé différemment dans les deux langues. En C, cette expression est une erreur de syntaxe, car la syntaxe d'une expression d'affectation en C est :

unary-expression '=' assignment-expression

En C++, il est analysé comme :

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

qui est une expression valide.

Si vous souhaitez utiliser une virgule en tant qu'opérateur dans un seul argument de fonction, une affectation de variable ou une autre liste séparée par des virgules, vous devez utiliser des parenthèses, par exemple :

int a = 1, b = 2, weirdVariable = (++a, b), d = 4;

Critique de la priorité des opérateurs de bits et d'égalité

La priorité des opérateurs logiques au niveau du bit a été critiquée. Conceptuellement, & et | sont des opérateurs arithmétiques comme * et +.

L'expression est syntaxiquement analysée comme alors que l'expression est analysée comme . Cela nécessite que les parenthèses soient utilisées plus souvent qu'elles ne le feraient autrement. a & b == 7a & (b == 7)a + b == 7(a + b) == 7

Historiquement, il n'y avait pas de distinction syntaxique entre les opérateurs binaires et logiques. En BCPL , B et au début du C, les opérateurs n'existaient pas. Au lieu de cela, ils avaient une signification différente selon qu'ils sont utilisés dans un « contexte de valeur de vérité » (c'est-à-dire lorsqu'une valeur booléenne était attendue, par exemple lorsqu'elle se comportait comme un opérateur logique, mais qu'elle se comportait comme une valeur au niveau du bit). Il a été conservé afin de conserver une rétrocompatibilité avec les installations existantes. && ||& |if (a==b & c) {...}c = a & b

De plus, en C++ (et dans les versions ultérieures de C), les opérations d'égalité, à l'exception de l'opérateur de comparaison à trois voies, produisent des valeurs de type bool qui sont conceptuellement un seul bit (1 ou 0) et en tant que telles n'appartiennent pas correctement à " " opérations.

Synonymes de l'opérateur C++

C++ définit certains mots-clés pour agir comme des alias pour un certain nombre d'opérateurs :

Mot-clé Opérateur
and &&
and_eq &=
bitand &
bitor |
compl ~
not !
not_eq !=
or ||
or_eq |=
xor ^
xor_eq ^=

Ceux-ci peuvent être utilisés exactement de la même manière que les symboles de ponctuation qu'ils remplacent, car ce ne sont pas le même opérateur sous un nom différent, mais plutôt de simples remplacements de jetons pour le nom (chaîne de caractères) de l'opérateur respectif. Cela signifie que les expressions (a > 0 and not flag)et (a > 0 && !flag)ont des significations identiques. Cela signifie également que, par exemple, le bitandmot-clé peut être utilisé pour remplacer non seulement l' opérateur au niveau du bit et mais aussi l' opérateur adresse de , et il peut même être utilisé pour spécifier des types de référence (par exemple, int bitand ref = n). La spécification ISO C tient compte de ces mots clés en tant que macros de préprocesseur dans le fichier d'en-tête iso646.h. Pour la compatibilité avec C, C++ fournit l'en-tête ciso646, dont l'inclusion n'a aucun effet.

Voir également

Les références

Liens externes