172 votes

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

Je lisais juste un code et j'ai découvert que la personne utilisait arr[-2] pour accéder au 2ème élément avant le arr comme ça :

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

Est-ce que c'est autorisé ?

Je sais que arr[x] est la même chose que *(arr + x) . Donc arr[-2] est *(arr - 2) ce qui semble correct. Qu'en pensez-vous ?

226voto

Matthew Flaschen Points 131723

C'est exact. De C99 §6.5.2.1/2 :

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

Il n'y a pas de magie. C'est une équivalence de 1 à 1. Comme toujours lors du déréférencement d'un pointeur (*), vous devez être sûr qu'il pointe vers une adresse valide.

2 votes

Notez également que vous n'avez pas besoin de déréférencer le pointeur pour obtenir UB. Il suffit de calculer somearray-2 est indéfini à moins que le résultat ne soit dans l'intervalle allant du début de somearray à 1 de son extrémité.

47 votes

Dans les livres plus anciens, le [] ont été référencés en tant que sucre de syntaxe pour l'arithmétique des pointeurs. Favoris La meilleure façon d'embrouiller les débutants est d'écrire 1[arr] - au lieu de arr[1] - et les regarder deviner ce que ça veut dire.

5 votes

Que se passe-t-il sur les systèmes 64 bits (LP64) lorsque vous avez un index int 32 bits qui est négatif ? L'index doit-il être promu en un int signé 64 bits avant le calcul de l'adresse ?

92voto

James McNellis Points 193607

Ceci n'est valable 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édez à la mémoire en dehors des limites du tableau. Ainsi, par exemple, ceci serait faux :

int arr[10];

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

Mais ça 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.

0 votes

Je n'irais pas jusqu'à dire que c'est invalide, juste potentiellement désordonné.

21 votes

@Matt : Le code dans le premier exemple produit un comportement non défini.

0 votes

BSTR est un bon exemple sous Windows. Tout allocateur de débogage. Rien de mal à cela.

16voto

Matt Joiner Points 29194

Ça me semble correct. Il serait toutefois rare que vous en ayez légitimement besoin.

15 votes

Ce n'est pas que rare - il est très utile, par exemple, dans le traitement des images avec des opérateurs de voisinage.

0 votes

J'avais juste besoin d'utiliser ceci parce que je crée un pool de mémoire avec une pile et un tas [ structure / conception ] . La pile croît vers des adresses mémoire plus élevées, le tas croît vers des adresses mémoire plus basses. Rencontre au milieu.

9voto

Igor Zevaka Points 32586

Ce qui était probablement arr pointait vers le milieu de la matrice, ce qui rendait arr[-2] pointant vers quelque chose dans le tableau original sans sortir des limites.

7voto

Paul R Points 104036

Je ne suis pas sûr de la fiabilité de cette information, mais je viens de lire la mise en garde suivante concernant les indices de tableau négatifs sur les systèmes 64 bits (LP64 vraisemblablement) : http://www.devx.com/tips/Tip/41349

L'auteur semble dire que les indices de tableau int 32 bits avec un adressage 64 bits peuvent entraîner de mauvais calculs d'adresse à moins que l'indice de tableau ne soit explicitement promu à 64 bits (par exemple via un cast ptrdiff_t). J'ai déjà vu un bug de cette nature avec la version PowerPC de gcc 4.1.0, mais je ne sais pas s'il s'agit d'un bug de compilation (c'est-à-dire qu'il devrait fonctionner selon la norme C99) ou d'un comportement correct (c'est-à-dire que l'index a besoin d'un cast vers 64 bits pour un comportement correct) ?

3 votes

Cela ressemble à un bug du compilateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X