Creo que las otras respuestas se están perdiendo algo.
Sí, p[i]
es por definición equivalente a *(p+i)
, que (porque la suma es conmutativa) es equivalente a *(i+p)
, que (de nuevo, por definición del []
operador) es equivalente a i[p]
.
(Y en array[i]
, el nombre de la matriz se convierte implícitamente en un puntero al primer elemento de la matriz).
Pero la conmutatividad de la suma no es tan obvia en este caso.
Cuando ambos operandos son del mismo tipo, o incluso de diferentes tipos numéricos que se promueven a un tipo común, la conmutatividad tiene mucho sentido: x + y == y + x
.
Pero en este caso estamos hablando específicamente de la aritmética de punteros, donde un operando es un puntero y el otro es un número entero. (Entero + entero es una operación diferente, y puntero + puntero no tiene sentido).
La descripción del +
operador del estándar C ( N1570 6.5.6) dice:
Además, ambos operandos tendrán un tipo aritmético o un operando será un puntero a un tipo de objeto completo y el otro tendrá un tipo entero.
Podría haber dicho con la misma facilidad:
Además, ambos operandos tendrán un tipo aritmético o el
operando izquierdo será un puntero a un tipo de objeto completo y el operando derecho
tendrá un tipo entero.
en cuyo caso ambos i + p
yi[p]
sería ilegal.
En términos de C ++, realmente tenemos dos conjuntos de +
operadores sobrecargados , que pueden describirse libremente como:
pointer operator+(pointer p, integer i);
y
pointer operator+(integer i, pointer p);
de los cuales solo el primero es realmente necesario.
Entonces, ¿por qué es así?
C ++ heredó esta definición de C, que la obtuvo de B (la conmutatividad de la indexación de matrices se menciona explícitamente en la Referencia de usuarios de 1972 a B ), que la obtuvo de BCPL (manual fechado en 1967), que bien podría haberla obtenido incluso idiomas anteriores (CPL? Algol?).
Entonces, la idea de que la indexación de matrices se define en términos de suma, y esa suma, incluso de un puntero y un entero, es conmutativa, se remonta muchas décadas atrás, a los lenguajes ancestrales de C.
Esos lenguajes fueron mucho menos fuertemente tipados que el C moderno. En particular, a menudo se ignoraba la distinción entre punteros y enteros. (Los primeros programadores de C a veces usaban punteros como enteros sin signo, antes deunsigned
palabra clave se agregara al lenguaje). Por lo tanto, la idea de hacer que la suma no sea conmutativa porque los operandos son de diferentes tipos probablemente no se les habría ocurrido a los diseñadores de esos idiomas. Si un usuario quería agregar dos "cosas", ya sea que esas "cosas" sean números enteros, punteros u otra cosa, no dependía del idioma evitarlo.
Y a lo largo de los años, cualquier cambio en esa regla habría roto el código existente (aunque el estándar ANSI C de 1989 podría haber sido una buena oportunidad).
Cambiar C y / o C ++ para requerir colocar el puntero a la izquierda y el entero a la derecha podría romper algún código existente, pero no habría pérdida de poder expresivo real.
Así que ahora tenemos arr[3]
y 3[arr]
significamos exactamente lo mismo, aunque la última forma nunca debería aparecer fuera del IOCCC .