Je pense que quelque chose manque aux autres réponses.
Oui, p[i]
est par définition équivalent à *(p+i)
, qui (parce que l'addition est commutative) est équivalent à *(i+p)
, qui (encore une fois, par la définition de l' []
opérateur) est équivalent à i[p]
.
(Et dans array[i]
, le nom du tableau est implicitement converti en un pointeur vers le premier élément du tableau.)
Mais la commutativité de l'addition n'est pas si évidente dans ce cas.
Lorsque les deux opérandes sont du même type, ou même de différents types numériques qui sont promus à un type commun, commutativité est parfaitement logique: x + y == y + x
.
Mais dans ce cas, nous parlons spécifiquement de l'arithmétique des pointeurs, où un opérande est un pointeur et l'autre est un entier. (Entier + entier est une opération différente et pointeur + pointeur est un non-sens.)
La description de l' +
opérateur par la norme C ( N1570 6.5.6) dit:
De plus, soit les deux opérandes doivent avoir un type arithmétique, soit un opérande doit être un pointeur vers un type d'objet complet et l'autre doit avoir un type entier.
Il aurait tout aussi bien pu dire:
De plus, soit les deux opérandes doivent être de type arithmétique, soit l'
opérande de gauche doit être un pointeur vers un type d'objet complet et l' opérande de droite
doit avoir un type entier.
auquel cas les deux i + p
et i[p]
seraient illégaux.
En termes C ++, nous avons vraiment deux ensembles d' +
opérateurs surchargés , qui peuvent être décrits de manière générale comme:
pointer operator+(pointer p, integer i);
et
pointer operator+(integer i, pointer p);
dont seul le premier est vraiment nécessaire.
Alors pourquoi est-ce ainsi?
C ++ a hérité de cette définition de C, qui l'a obtenue de B (la commutativité de l'indexation de tableaux est explicitement mentionnée dans la référence des utilisateurs de 1972 à B ), qui l'a obtenue de BCPL (manuel daté de 1967), qui pourrait bien l'avoir obtenue de même langues antérieures (CPL? Algol?).
Ainsi, l'idée que l'indexation de tableaux est définie en termes d'addition, et que l'addition, même d'un pointeur et d'un entier, est commutative, remonte à plusieurs décennies, aux langages des ancêtres de C.
Ces langages étaient beaucoup moins fortement typés que le C moderne. En particulier, la distinction entre pointeurs et entiers a souvent été ignorée. (Les premiers programmeurs C utilisaient parfois des pointeurs comme des entiers non signés, avant que le unsigned
mot - clé ne soit ajouté au langage.) Ainsi, l'idée de rendre l'addition non commutative parce que les opérandes sont de types différents n'aurait probablement pas surgi pour les concepteurs de ces langages. Si un utilisateur voulait ajouter deux "choses", que ces "choses" soient des entiers, des pointeurs ou autre chose, ce n'était pas à la langue de l'empêcher.
Et au fil des ans, toute modification de cette règle aurait violé le code existant (bien que la norme ANSI C de 1989 ait pu être une bonne opportunité).
Changer C et / ou C ++ pour exiger de placer le pointeur à gauche et l'entier à droite pourrait casser du code existant, mais il n'y aurait aucune perte de puissance expressive réelle.
Nous avons donc maintenant arr[3]
et 3[arr]
signifiant exactement la même chose, bien que cette dernière forme ne devrait jamais apparaître en dehors de l' IOCCC .