web-dev-qa-db-fra.com

Les index de tableaux négatifs sont-ils autorisés en C?

Je venais de lire du code et j'ai constaté que la personne utilisait arr[-2] Pour accéder au 2e élément avant le arr, comme ceci:

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

Est-ce permis?

Je sais que arr[x] Est identique à *(arr + x). Donc arr[-2] Est *(arr - 2), ce qui semble bien. Qu'est-ce que tu penses?

101
bodacydo

C'est correct. À partir de C99 §6.5.2.1/2:

La définition de l'opérateur en indice [] est que E1 [E2] est identique à (* ((E1) + (E2))).

Il n'y a pas de magie. C'est une équivalence 1-1. Comme toujours lors de la déréférence d'un pointeur (*), vous devez vous assurer qu'il pointe vers une adresse valide.

160
Matthew Flaschen

Ceci n'est valide que si arr est un pointeur qui pointe vers le deuxième élément d'un tableau ou un élément ultérieur. Sinon, il n'est pas valide, car vous accéderiez à la mémoire en dehors des limites du tableau. Donc, par exemple, ce serait faux:

int arr[10];

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

Mais ce serait bien:

int arr[10];
int* p = &arr[2];

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

Il est toutefois inhabituel d’utiliser un indice négatif.

62
James McNellis

Cela me semble bien. Il serait cependant rare que vous en ayez légitimement besoin.

10
Matt Joiner

Ce qui était probablement que arr pointait au milieu du tableau, rendant ainsi arr[-2] montrant quelque chose dans le tableau d'origine sans sortir du cadre.

7
Igor Zevaka

Je ne sais pas si cela est fiable, mais je viens de lire la mise en garde suivante à propos des indices de tableaux négatifs sur les systèmes 64 bits (sans doute du type LP64): http://www.devx.com/tips/Tip/41349

L’auteur semble dire que les index de tableau int de 32 bits avec un adressage de 64 bits peuvent donner lieu à des calculs d’adresses erronées à moins que l’indice de tableau ne soit explicitement promu à 64 bits (par exemple, via une conversion ptrdiff_t). J'ai effectivement vu un bogue de sa nature avec la version PowerPC de gcc 4.1.0, mais je ne sais pas s'il s'agit d'un bogue de compilateur (c'est-à-dire qu'il devrait fonctionner selon le standard C99) ou d'un comportement correct (c'est-à-dire que l'index doit être converti en 64 bits pour un comportement correct)?

7
Paul R

Pour savoir pourquoi quelqu'un voudrait utiliser des index négatifs, je les ai utilisés dans deux contextes:

  1. Avoir une table de nombres combinatoires qui vous dit peigne [1] [- 1] = 0; vous pouvez toujours vérifier les index avant d'accéder à la table, mais le code est ainsi plus propre et s'exécute plus rapidement.

  2. Mettre un centinel au début d'une table. Par exemple, vous voulez utiliser quelque chose comme

     while (x < a[i]) i--;
    

mais alors vous devriez aussi vérifier que i est positif.
Solution: faites en sorte que a[-1] est -DBLE_MAX, pour que x&lt;a[-1] sera toujours faux.

1

Je sais que la question a reçu une réponse, mais je n'ai pas pu m'empêcher de partager cette explication.

Je me souviens des principes de la conception du compilateur. Supposons que a soit un tableau int et que la taille de int soit 2, et que l’adresse de base pour a soit 1000.

Comment a[5] fonctionnera ->

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

Cette explication est également la raison pour laquelle les index négatifs dans les tableaux fonctionnent en C.

c'est-à-dire si j'accède à a[-5] ça va me donner

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

Il me retournera objet à l'emplacement 990. Par cette logique, nous pouvons accéder aux index négatifs dans Array en C.

1
Ajinkya Patil