Penso che qualcosa venga perso dalle altre risposte.
Sì, p[i]
è per definizione equivalente a *(p+i)
, che (poiché l'addizione è commutativa) è equivalente a *(i+p)
, che (di nuovo, per definizione []
dell'operatore) è equivalente a i[p]
.
(E in array[i]
, il nome dell'array viene convertito implicitamente in un puntatore al primo elemento dell'array.)
Ma la commutatività dell'addizione non è poi così ovvia in questo caso.
Quando entrambi gli operandi sono dello stesso tipo, o anche di diversi tipi numerici che sono promosso un tipo comune, commutatività rende perfettamente senso: x + y == y + x
.
Ma in questo caso stiamo parlando specificamente dell'aritmetica del puntatore, in cui un operando è un puntatore e l'altro è un numero intero. (Numero intero + intero è un'operazione diversa e puntatore + puntatore è senza senso.)
La descrizione dello standard C del +
dell'operatore ( N1570 6.5.6) dice:
Inoltre, entrambi gli operandi devono avere un tipo aritmetico oppure un operando deve essere un puntatore a un tipo di oggetto completo e l'altro deve avere un tipo intero.
Avrebbe potuto altrettanto facilmente dire:
Inoltre, entrambi gli operandi devono avere un tipo aritmetico oppure l'
operando di sinistra deve essere un puntatore a un tipo di oggetto completo e il operando di destra
deve avere un tipo intero.
nel qual caso entrambi i + p
e i[p]
sarebbe illegale.
In termini di C ++, abbiamo davvero due serie di +
operatori sovraccarichi , che possono essere liberamente descritti come:
pointer operator+(pointer p, integer i);
e
pointer operator+(integer i, pointer p);
di cui solo il primo è veramente necessario.
Allora perché è così?
Il C ++ ha ereditato questa definizione da C, che l'ha ottenuta da B (la commutatività dell'indicizzazione di array è esplicitamente menzionata nel riferimento degli utenti a B del 1972 ), che l'ha ottenuta da BCPL (manuale del 1967), che potrebbe averlo ottenuto anche da lingue precedenti (CPL? Algol?).
Quindi l'idea che l'indicizzazione di array sia definita in termini di addizione e che l'addizione, anche di un puntatore e di un numero intero, sia commutativa, risale a molti decenni fa ai linguaggi antenati di C.
Quelle lingue erano tipizzate in modo molto meno marcato di quanto non lo sia la C moderna. In particolare, la distinzione tra puntatori e numeri interi è stata spesso ignorata. (I primi programmatori C a volte usavano i puntatori come numeri interi senza segno, prima delunsigned
parola chiave fosse aggiunta al linguaggio.) Quindi l'idea di rendere l'aggiunta non commutativa perché gli operandi sono di tipi diversi probabilmente non sarebbe venuta ai progettisti di quei linguaggi. Se un utente voleva aggiungere due "cose", indipendentemente dal fatto che quelle "cose" fossero numeri interi, puntatori o qualcos'altro, non era nella lingua per impedirlo.
E nel corso degli anni, qualsiasi modifica a quella regola avrebbe infranto il codice esistente (anche se lo standard ANSI C del 1989 avrebbe potuto essere una buona opportunità).
La modifica di C e / o C ++ per richiedere il posizionamento del puntatore a sinistra e il numero intero a destra potrebbero rompere un po 'di codice esistente, ma non ci sarebbe perdita di reale potere espressivo.
Quindi ora abbiamo arr[3]
e intendiamo 3[arr]
esattamente la stessa cosa, sebbene quest'ultima forma non dovrebbe mai apparire al di fuori dell'IOCCC .