Myślę, że inne odpowiedzi pomijają coś.
Tak, p[i]
z definicji jest równoważne z tym *(p+i)
, co (ponieważ dodawanie jest przemienne) jest równoważne z *(i+p)
, co (ponownie, z definicji []
operatora) jest równoważne i[p]
.
(A array[i]
wewnątrz nazwa tablicy jest domyślnie konwertowana na wskaźnik do pierwszego elementu tablicy).
Ale zamienność dodawania nie jest w tym przypadku aż tak oczywista.
Gdy oba operandy są tego samego typu, a nawet różnych typów numerycznych, które są promowane do wspólnego typu, przemienność sens: x + y == y + x
.
Ale w tym przypadku mówimy konkretnie o arytmetyce wskaźnika, gdzie jeden operand jest wskaźnikiem, a drugi liczbą całkowitą. (Liczba całkowita + liczba całkowita to inna operacja, a wskaźnik + wskaźnik to nonsens).
Opis +
operatora w standardzie C ( N1570 6.5.6) mówi:
Ponadto oba operandy muszą mieć typ arytmetyczny lub jeden operand powinien być wskaźnikiem do pełnego typu obiektu, a drugi powinien być liczbą całkowitą.
Równie łatwo mógłby powiedzieć:
Ponadto oba operandy muszą mieć typ arytmetyczny lub lewy
operand powinien być wskaźnikiem do pełnego typu obiektu, a prawy operand
powinien być liczbą całkowitą.
w takim przypadku oba i + p
i i[p]
byłyby nielegalne.
W języku C ++ mamy naprawdę dwa zestawy przeciążonych +
operatorów, które można luźno opisać jako:
pointer operator+(pointer p, integer i);
i
pointer operator+(integer i, pointer p);
z których tylko pierwszy jest naprawdę potrzebny.
Więc dlaczego tak jest?
C ++ odziedziczył tę definicję od C, która otrzymała ją od B (przemienność indeksowania tablic jest wyraźnie wspomniana w Odniesieniu użytkowników do B z 1972 r. ), Która otrzymała ją od BCPL (instrukcja z 1967 r.), Która mogła ją nawet otrzymać wcześniejsze języki (CPL? Algol?).
Pomysł, że indeksowanie tablic jest zdefiniowane w kategoriach dodawania i że dodawanie, nawet wskaźnika i liczby całkowitej, jest przemienne, sięga wielu dziesięcioleci do języków przodków C.
Języki te były znacznie rzadziej pisane niż współczesne C. W szczególności rozróżnianie wskaźników i liczb całkowitych było często ignorowane. (Wcześniejsi programiści C czasami używali wskaźników jako liczb całkowitych bez znaku, zanim unsigned
słowo kluczowe zostało dodane do języka). Więc pomysł, aby dodanie było nieprzemienne, ponieważ operandy różnych typów prawdopodobnie nie przyszedłby do projektantów tych języków. Jeśli użytkownik chciał dodać dwie „rzeczy”, bez względu na to, czy są to liczby całkowite, wskaźniki lub coś innego, język nie był w stanie temu zapobiec.
Z biegiem lat każda zmiana tej reguły złamałaby istniejący kod (chociaż norma ANSI C z 1989 roku mogła być dobrą okazją).
Zmiana C i / lub C ++ w taki sposób, aby wymagała umieszczenia wskaźnika po lewej stronie i liczby całkowitej po prawej stronie, może zepsuć istniejący kod, ale nie nastąpiłaby utrata prawdziwej mocy ekspresyjnej.
Mamy więc teraz arr[3]
i 3[arr]
dokładnie to samo, chociaż ta ostatnia forma nigdy nie powinna pojawić się poza IOCCC .