Zijn negatieve array-indexen toegestaan ​​in C?

Ik was net wat code aan het lezen en ontdekte dat de persoon arr[-2]gebruikte om toegang te krijgen tot het 2e element vóór de arr, zoals zo:

|a|b|c|d|e|f|g|
       ^------------ arr[0]
         ^---------- arr[1]
   ^---------------- arr[-2]

Mag dat?

Ik weet dat arr[x]hetzelfde is als *(arr + x). Dus arr[-2]is *(arr - 2), wat goed lijkt. Wat denk je?


Antwoord 1, autoriteit 100%

Dat klopt. Vanaf C99 §6.5.2.1/2:

De definitie van het subscript
operator [] is dat E1[E2] is
identiek aan (*((E1)+(E2))).

Er is geen magie. Het is een 1-1 equivalentie. Zoals altijd wanneer u een verwijzing naar een aanwijzer (*) verwijdert, moet u er zeker van zijn dat deze naar een geldig adres verwijst.


Antwoord 2, autoriteit 39%

Dit is alleen geldig als arreen pointer is die verwijst naar het tweede element in een array of een later element. Anders is het niet geldig, omdat u toegang zou krijgen tot geheugen buiten de grenzen van de array. Dit zou bijvoorbeeld verkeerd zijn:

int arr[10];
int x = arr[-2]; // invalid; out of range

Maar dit zou goed zijn:

int arr[10];
int* p = &arr[2];
int x = p[-2]; // valid:  accesses arr[0]

Het is echter ongebruikelijk om een ​​negatief subscript te gebruiken.


Antwoord 3, autoriteit 8%

Klinkt goed voor mij. Het zou echter zelden voorkomen dat u het legitiem nodig zou hebben.


Antwoord 4, autoriteit 5%

Waarschijnlijk was dat arrnaar het midden van de array wees, waardoor arr[-2]naar iets in de originele array wees zonder buiten de grenzen te gaan .


Antwoord 5, autoriteit 4%

Ik weet niet zeker hoe betrouwbaar dit is, maar ik las zojuist het volgende voorbehoud over negatieve array-indexen op 64-bits systemen (vermoedelijk LP64): http://www.devx.com/tips/Tip/41349

De auteur lijkt te zeggen dat 32-bits int-array-indexen met 64-bits adressering kunnen resulteren in slechte adresberekeningen, tenzij de array-index expliciet wordt gepromoveerd tot 64 bits (bijvoorbeeld via een ptrdiff_t-cast). Ik heb eigenlijk een bug van zijn aard gezien met de PowerPC-versie van gcc 4.1.0, maar ik weet niet of het een compilerbug is (dwz zou moeten werken volgens de C99-standaard) of correct gedrag (dwz index heeft een cast nodig naar 64 bits voor correct gedrag) ?


Antwoord 6, autoriteit 2%

Ik weet dat de vraag is beantwoord, maar ik kon het niet laten om deze uitleg te delen.

Ik herinner me de principes van compilerontwerp: laten we aannemen dat aeen int-array is en dat de grootte van int2, en het basisadres voor ais 1000.

Hoe werkt a[5]->

Base Address of your Array a + (index of array *size of(data type for array a))
Base Address of your Array a + (5*size of(data type for array a))
i.e. 1000 + (5*2) = 1010

Deze verklaring is ook de reden waarom negatieve indexen in arrays werken in C; d.w.z. als ik a[-5]benader, krijg ik:

Base Address of your Array a + (index of array *size of(data type for array a))
Base Address of your Array a + (-5 * size of(data type for array a))
i.e. 1000 + (-5*2) = 990

Het zal het object op locatie 990 retourneren. Dus door deze logica hebben we toegang tot negatieve indexen in arrays in C.

Other episodes