Voici un tableau qui liste la précédence et l’associativité de tous les opérateurs des langages C et C++ (lorsque les opérateurs existent aussi en Java, Perl, PHP et bien d’autres langages récents, la précédence est la même que celle donnée). Les opérateurs sont classés de haut en bas, par ordre de préséance décroissante. La préséance descendante fait référence à la priorité du regroupement des opérateurs et des opérandes. Dans le cas d’une expression, un opérateur figurant sur une certaine ligne sera groupé avant tout opérateur figurant sur une ligne inférieure. Les opérateurs qui se trouvent dans la même cellule (il peut y avoir plusieurs rangées d’opérateurs listés dans une cellule) sont regroupés avec la même préséance, dans la direction donnée. La précédence 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 phrases. Le tableau donné ici a été déduit de cette 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 précédence des opérateurs C, et indique également que la précédence des opérateurs résultant de la grammaire suit de près l’ordre des sections de la spécification :
« La syntaxe spécifie la précédence des opérateurs dans l’évaluation d’une expression, qui est la même que l’ordre des sous-clauses majeures de cette sous-clause, la plus haute précédence en premier. »
Un tableau de précédence, bien que le plus souvent adéquat, ne peut résoudre quelques détails. En particulier, notez que l’opérateur ternaire permet n’importe quelle expression arbitraire en tant qu’opérande du milieu, bien qu’il soit répertorié comme ayant une précédence plus élevée que les opérateurs d’affectation et de virgule. Ainsi, a ? b, c : d
est interprété comme a ? (b, c) : d
, et non comme l’inutile (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, non parenthésé, d’une expression cast C ne peut pas être l’opérande de sizeof
. Par conséquent, sizeof (int) * x
est interprété comme (sizeof(int)) * x
et non sizeof ((int) * x)
.
NotesEdit
Le tableau de précédence détermine l’ordre de liaison dans les expressions chaînées, lorsqu’il n’est pas expressément spécifié par les parenthèses.
Précédence et liaisons
Plusieurs des 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 facturée, plutôt que par une table de précédence. Cela crée quelques conflits subtils. Par exemple, en C, la syntaxe d’une expression conditionnelle est:
logical-OR-expression ? expression : conditional-expression
alors qu’en C++ elle est :
logical-OR-expression ? expression : assignment-expression
Hence, l’expression:
e = a < d ? a++ : a = d
est analysée différemment dans les deux langages. 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++, elle est analysée comme:
e = (a < d ? a++ : (a = d))
ce qui est une expression valide.
int a = 1, b = 2, weirdVariable = (++a, b), d = 4;
Critique de la précédence des opérateurs de type bitwise et égalitéEdit
La précédence des opérateurs logiques bitwise a été critiquée. Conceptuellement, & et | sont des opérateurs arithmétiques comme * et +.
De plus, en C++ (et dans les versions ultérieures du C), les opérations d’égalité, à l’exception de l’opérateur de comparaison à trois, donnent des valeurs de type bool qui sont conceptuellement un seul bit (1 ou 0) et, en tant que telles, n’appartiennent pas correctement aux opérations « bitwise ».
Synonymes d’opérateurs C++Modification
C++ définit certains mots-clés pour servir d’alias à un certain nombre d’opérateurs :
Mot clé | Opérateur |
---|---|
et |
&& |
and_eq |
&= |
bitand |
& |
bitor |
| |
compl |
~ |
not |
! |
not_eq |
!= |
or |
|| |
or_eq |
|= |
xor |
^ |
xor_eq |
^= |
Ils peuvent être utilisés exactement de la même manière que les symboles de ponctuation qu’ils remplacent, car il ne s’agit pas du même opérateur sous un nom différent, mais 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 et non drapeau)
et (a >&& !flag)
ont des significations identiques. Cela signifie également que, par exemple, le mot-clé bitand
peut être utilisé pour remplacer non seulement l’opérateur 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 bit-et 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 le C, le C++ fournit l’en-tête ciso646
, dont l’inclusion n’a aucun effet.