Właśnie czytałem kod i odkryłem, że osoba używała arr[-2]
dostępu do drugiego elementu przed arr
, na przykład:
|a|b|c|d|e|f|g|
^------------ arr[0]
^---------- arr[1]
^---------------- arr[-2]
Czy to jest dozwolone?
Wiem, że arr[x]
to to samo co *(arr + x)
. Tak arr[-2]
jest *(arr - 2)
, co wydaje się OK. Co myślisz?
somearray-2
są niezdefiniowane, chyba że wynik mieści się w zakresie od początkusomearray
do 1 po jego końcu.[]
były one określane jako cukier składniowy dla arytmetyki wskaźnikowej. Ulubionym sposobem na zmylenie początkujących jest pisanie1[arr]
- zamiastarr[1]
- i obserwowanie, jak zgadują, co to ma znaczyć.((E1)+(E2))
będzie (64-bitowym) wskaźnikiem z oczekiwaną wartością.Jest to poprawne tylko wtedy, gdy
arr
jest wskaźnikiem wskazującym na drugi element tablicy lub późniejszy element. W przeciwnym razie nie jest to poprawne, ponieważ miałbyś dostęp do pamięci poza granicami tablicy. Na przykład byłoby to błędne:Ale to byłoby w porządku:
Jednak użycie ujemnego indeksu dolnego jest niezwykłe.
źródło
int arr[10];
była częścią struktury z innymi elementami przed nią,arr[-2]
mogłaby być dobrze zdefiniowana i można by określić, czy jest opartaoffsetof
itp.If one is sure that the elements exist, it is also possible to index backwards in an array; p[-1], p[-2], and so on are syntactically legal, and refer to the elements that immediately precede p[0]. Of course, it is illegal to refer to objects that are not within the array bounds.
Mimo to twój przykład jest lepszy, ponieważ pomaga mi go zrozumieć. Dzięki!Brzmi dobrze. Byłoby to jednak rzadkim przypadkiem, gdy byś tego potrzebował.
źródło
To prawdopodobnie
arr
wskazywało na środek tablicy, a więcarr[-2]
wskazywało na coś w oryginalnej tablicy bez przekraczania granic.źródło
Nie jestem pewien, na ile jest to wiarygodne, ale właśnie przeczytałem następujące zastrzeżenie dotyczące ujemnych wskaźników tablicy w systemach 64-bitowych (prawdopodobnie LP64): http://www.devx.com/tips/Tip/41349
Autor wydaje się mówić, że 32-bitowe indeksy tablicy int z 64-bitowym adresowaniem mogą skutkować złymi obliczeniami adresu, chyba że indeks tablicy jest jawnie promowany do 64 bitów (np. Przez rzutowanie ptrdiff_t). Właściwie widziałem błąd jego natury w wersji PowerPC gcc 4.1.0, ale nie wiem, czy jest to błąd kompilatora (tj. Powinien działać zgodnie ze standardem C99), czy poprawne zachowanie (tj. Indeks wymaga rzutowania na 64 bity do prawidłowego zachowania)?
źródło
Wiem, że na pytanie udzielono odpowiedzi, ale nie mogłem się powstrzymać przed podzieleniem się tym wyjaśnieniem.
Pamiętam zasady projektowania kompilatora, załóżmy, że a jest tablicą int, a rozmiar int to 2, a adres bazowy a to 1000.
Jak
a[5]
będzie działać ->To wyjaśnienie jest również powodem, dla którego indeksy ujemne w tablicach działają w C.
tzn. jeśli uzyskam dostęp
a[-5]
, da miZwróci mi obiekt w lokalizacji 990. Dzięki tej logice możemy uzyskać dostęp do ujemnych indeksów w tablicy w C.
źródło
O tym, dlaczego ktoś miałby chcieć używać indeksów ujemnych, użyłem ich w dwóch kontekstach:
Posiadanie tabeli liczb kombinatorycznych, która mówi ci, że grzebień [1] [- 1] = 0; zawsze możesz sprawdzić indeksy przed uzyskaniem dostępu do tabeli, ale w ten sposób kod wygląda czysto i działa szybciej.
Umieszczenie centynela na początku stołu. Na przykład chcesz użyć czegoś takiego jak
ale powinieneś także sprawdzić, czy
i
jest pozytywny.Rozwiązanie: uczynić go tak, że
a[-1]
jest-DBLE_MAX
tak, żex<a[-1]
zawsze będzie fałszywa.źródło
źródło