Sans être très beau, c'est permis de faire ça :
??Code:
1
2
3 int* tab = new int[4]; int* t2 = tab + 1; t2[-1] = 8;
Ca ne me met pas de warning sous vs2005.
Version imprimable
Sans être très beau, c'est permis de faire ça :
??Code:
1
2
3 int* tab = new int[4]; int* t2 = tab + 1; t2[-1] = 8;
Ca ne me met pas de warning sous vs2005.
non un indice de tableau doit bien sur être de type size_t il me semble, donc un unsigned qqchose.
Aucun warning oO bizarre en tout cas. Segmentation fault à l'exécution au moins ?
EDIT remarque : c'est vrai qu'avec l'arithmétique des pointeurs, t[-1] est peut-être considéré tout simplement comme *(t-1), donc valable à la compilation. tu n'as pas déclaré tes variables comme des tableaux mais comme des pointeurs, ce qui devrait expliquer l'absence de warning.
Non aucune erreur à l'éxécution, mes indices, même négatifs, vont tapper dans une zone mémoire ok, si tu regardes mon exemple.
Bien sur faire la même chose avec un pur tableau statique, ca passe moins bien...
Salut,
Sous Gcc non plus, il n'y a pas d'avertissement quant à la dangerosité de la pratique ;)
Je ne serais pas plus étonné que cela d'apprendre que la norme (sans doute la norme C, d'ailleurs) a laissé ce comportement "undefined", mais ne réclame pas d'avertissement...
N'oublie pas que tab n'est jamais qu'une adresse (celle du premier élément du tableau, en l'occurence), et que le compilateur est donc parfaitement en mesure de calculer l'adresse représentée l'indice négatif.
Maintenant, on ne peut qu'insister sur le fait que la pratique est pour le moins dangereuse ;)
D'ailleurs, en C++, pour ce qui est de la classe vector, la norme précise que l'indice doit etre compris entre 0 et la taille du vecteur...
Citation:
Envoyé par la norme
Pour un vector, cela va de soit, à peu près autant que pour les tableaux. Mais en fait je vois de moins en moins de restrictions à l'utilisation d'un indice négatif pour un pointeur. J'ai bien dans la tête des algos C qui font :
C'est finalement la même chose avec un indice.Code:
1
2
3 int * p = tableauALEnvers(); while ( --count ) *(p--) = calc();
Je suis d'accord, c'est pas beau mais
t2[-1]
C'est pas égal à ?
t2[255] ou t2[65535] ou t2[4294967295]
suivant que l'indice est sur 1, 2 ou 4 octets.
C'est peut être pour cela que le compilateur, il ne crie pas. Il transforme implicitement un nombre signé en non signé
Mon idée à 2 balles
Quand je fais un cout, j'ai bien 8 affiché donc il ne fait pas cette conversion.
pour ram_000 -> ici en fait ce n'est pas [-1] sur un tableau statique, mais sur un pointeur. Donc il faut en déduire que ptr[nombre] n'accède pas "à l'indice nombre" du tableau (qui doit etre non-signé, donc qui présente peut être le risque que tu décris), mais interpréter ça comme un simple raccourci d'écriture pour *(ptr+nombre*sizeof(type pointé)) (arithmétique des pointeurs, le nombre peut être positif ou négatif).
Je trouve cela normal que ça ne génère pas d'erreur, et comme je vois mal le compilateur bien comprendre si la zone mémoire accédée est valide pour le programme ou non, je commence à comprendre pourquoi il ne peut pas faire de warning non plus.
Et ce, d'autant plus que, par définition, un entier (je ne sais plus s'il ne s'agirait pas par hasard des entiers non signés :oops:) est sensé représenter l'ensemble des adresses susceptibles d'exister...
Or, il n'y a rien à faire, si même on prend (par facilité) pour base l'octet, cela signifie que l'adresse du premier élément se trouve entre 1 et 255 (étant entendu que l'adresse 0 est considérée comme l'adresse invalide ;)).
Dés lors, si on rajoute l'équivalent non signé de -1 (disons, pour la facilité, mais en accord avec l'exemple 255 ), l'adresse obtenue restera... celle du premier élément du tableau - la taille du type concerné.
Formellement, l'opérateur [] n'est pas un opérateur d'indice de tableau, mais un opérateur d'addition de pointeur, suivi de déréférencement...
Donc, par définition,
D'ailleurs, plus drôle encore, rien n'oblige que ce soit l'élément en dehors des crochets qui soit le pointeur, et donc :Code:t2[-1] == *(t2 + (-1))
(je ne sais plus si les parenthèses sont nécessaires).Code:t2[-1] == (-1)[t2]
C'est totalement normal, et on peut même écrire le pointeur à la place de l'indice et l'indice à la place du pointeur vu qu'au final tout est remplacé comme certains l'ont indiqué par une somme de pointeur + entier, avec déréférencement :
Code:std::cout << 0[tab] << std::endl;
afficheront 8.Code:std::cout << (-1)[t2] << std::endl;
Edit : grillé...
Et oui les parenthèses sont nécessaires.