[C] soustraire deux pointeurs

soustraire deux pointeurs [C] - C - Programmation

Marsh Posté le 17-01-2011 à 21:40:04    

Bonjour à tous,  
 
Je suis débutant en prog', je me pose une question sur l'emploi des pointeurs en C. Je la soumets à votre sagacité.  
 
Supposons donné un tableau (disons d'entiers) et un pointeur vers un entier qui se promène dans ce tableau, comme dans :

Code :
  1. int* pint = my_int_array ;
  2. while (foo){
  3.     pint++;
  4.     foo = bar(foo, *pint);
  5. }


 
Comment pourrais-je évaluer d'une manière élégante la position du pointeur dans mon tableau ? J'avais pensé à faire :

Code :
  1. int rank = (pint - my_int_array) / sizeof( int);


mais je reçois une erreur de typage.
 
J'ai lu qu'il n'existe pas d'opérateur de conversion d'un pointeur vers un entier, c'est pourtant un peu ce que je voudrais faire : obtenir la partie adresse du pointeur sous forme d'un entier (ou d'un long ptet' ) ?
 
Merci de votre lecture  
 
ced'


Message édité par unecrepe le 17-01-2011 à 21:42:23
Reply

Marsh Posté le 17-01-2011 à 21:40:04   

Reply

Marsh Posté le 17-01-2011 à 22:53:52    

un cast ?


---------------
Aimer les femmes intelligentes est un plaisir de pédéraste. (Charles Baudelaire) - Vous vulgarisez :o (Jean-Kevin Dubois)
Reply

Marsh Posté le 17-01-2011 à 23:00:35    

merci de ta réponse, qu'a le mérite d'économiser les disques durs du serveur !
 
Tu voudrais bien développer un peu ce que tu veux dire par là (un exemple de code ou bien un lien) steup ?

Reply

Marsh Posté le 17-01-2011 à 23:16:08    

rank=((int)pint - (int)my_int_array) / sizeof( int);


---------------
Aimer les femmes intelligentes est un plaisir de pédéraste. (Charles Baudelaire) - Vous vulgarisez :o (Jean-Kevin Dubois)
Reply

Marsh Posté le 17-01-2011 à 23:22:16    

Merci de ton aide !
 
En fait ce truc retourne une erreur de taille d'entier donc il faut remplacer les (int) par des (long)
 

Reply

Marsh Posté le 18-01-2011 à 11:01:15    

Donne du code complet parce qu'il ne devrait pas etre necessaire d'utiliser des cast pour ca.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 18-01-2011 à 11:16:23    

La division par sizeof(int) me parait curieuse (voire en trop).
Il devrait même être possible, grace à l'arithmétique des pointeurs, de faire directement :
rank = pint - my_int_array;
 
Après tout, pour accéder à l'élément de rang i dans le tableau , on fait juste :
 
pint = my_int_array + i;
 
de même que l'instruction pint++ fait avancer le pointeur sur l'élément suivant, quelle que soit sa taille.

Reply

Marsh Posté le 18-01-2011 à 13:48:23    

Merci de votre aide.
 
Vous avez raison, l'arithmétique des pointeurs fonctionne comme on s'y attend :
 
on a un opérateur - (moins) qui à un couple de pointeurs du même type associe un entier correspondant à la différence des adresses divisée par la taille du type en question.
 
On donc a en fait toujours

Code :
  1. pint - my_int_array == ((long)(pint) - (long)(my_int_array))/sizeof(int)


 
J'avais mal interprété un message d'erreur qui venait du fait que mon pointeur n'avait pas été initialisé, ou je ne sais plus trop quoi. :)
 

Reply

Marsh Posté le 18-01-2011 à 17:28:57    

Oui: L'arithmétique des pointeurs, c'est exactement fait pour cela:

Citation :

p2 - p1 = (adresse contenue dans p2 - adresse contenue dans p1) /taille(éléments pointés par p1 et p2)
 
Le type du résultat de la soustraction de deux pointeurs est très dépendant de la machine cible et du modèle mémoire du programme. En général, on ne pourra jamais supposer que la soustraction de deux pointeurs est un entier (que les chevronnés du C me pardonnent, mais c'est une erreur très grave). En effet, ce type peut être insuffisant pour stocker des adresses (une machine peut avoir des adresses sur 64 bits et des données sur 32 bits). Pour résoudre ce problème, le fichier d'en-tête stdlib.h contient la définition du type à utiliser pour la différence de deux pointeurs. Ce type est nommé ptrdiff_t.

( http://cpp.developpez.com/cours/cpp/?page=page_6#LVI-H )
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 18-01-2011 à 18:24:51    

Merci pour le lien et le tuyau sur ptrdiff_t. Je conçois que les soustractions de pointeurs soient effectivement une source potentielle d'erreur sérieuse. Le type ptrdiff_t n'est pas renseigné dans K&R à la page de stdlib.h, à moins que je ne me fourvoie. C'est parce qu'il est apparu dans une version postérieure de stdlib ou bien K&R n'est pas exhaustif ?
 
J'en profite pour ajouter à tout hasard que l'on peut aussi comparer deux adresses :
 

Code :
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main(){
  4. int *pint, my_array[3] = { 0 ,  1 , 2 } ;
  5. pint = my_array ;
  6. pint ++ ;
  7. if (pint > my_array){
  8.  printf("Pointer comparisons DO work in C! \n" );
  9. }
  10. return 0 ;
  11. }


 
On ne peut en revanche pas multiplier un pointeur par quoi que ce soit, mais toutes les opérations définies sur le type int s'étendent naturellement à ptrdiff_t. Il faut par contre faire attention au fait que si je soustrais deux pointeurs du même type et que j'incrémente un pointeur d'un autre type de cette différence, il n'y a pas de conversions de taille. J'espère que ce morceau de code éclaire ce que je veux dire :
 

Code :
  1. char *pchar ;
  2. pchar = malloc( sizeof (char));
  3. printf("%p \n", pchar);
  4. pchar += (pint - my_array) ;
  5. printf("%p \n", pchar);


 
Merci à nouveau !
 
Ced'

Reply

Marsh Posté le 18-01-2011 à 18:24:51   

Reply

Marsh Posté le 18-01-2011 à 19:40:07    

unecrepe a écrit :

Merci pour le lien et le tuyau sur ptrdiff_t. Je conçois que les soustractions de pointeurs soient effectivement une source potentielle d'erreur sérieuse. Le type ptrdiff_t n'est pas renseigné dans K&R à la page de stdlib.h, à moins que je ne me fourvoie. C'est parce qu'il est apparu dans une version postérieure de stdlib ou bien K&R n'est pas exhaustif ?

Le K&R, c'est le C des cavernes, ça s'est quand même étoffé depuis.
Une remarque en passant:

Citation :

Pointer arithmetic cannot be performed on void pointers because the void type has no size, and thus the pointed address can not be added to, although gcc and other compilers will perform byte arithmetic on void* as a non-standard extension.


A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 18-01-2011 à 20:34:27    

unecrepe a écrit :

Merci pour le lien et le tuyau sur ptrdiff_t. Je conçois que les soustractions de pointeurs soient effectivement une source potentielle d'erreur sérieuse. Le type ptrdiff_t n'est pas renseigné dans K&R à la page de stdlib.h, à moins que je ne me fourvoie. C'est parce qu'il est apparu dans une version postérieure de stdlib ou bien K&R n'est pas exhaustif ?

 

J'ai l'impression que tu te fourvoie (à moins que tu ais la première édition?): il est dans l'index de mon exemplaire qui référence la section 5.4 sur l'arithmétique des pointeurs, la section sur typedef où ptrdiff_t est donné comme un exemple et la section sur les opérateurs additifs dans la partie référence.  En passant, l'en-tête qui définit ptrdiff_t est stddef.h, pas stdlib.h.

 
Citation :

J'en profite pour ajouter à tout hasard que l'on peut aussi comparer deux adresses :[quotemsg]

 

Uniquement si elles pointent vers le même objet.

 

[quotemsg]Il faut par contre faire attention au fait que si je soustrais deux pointeurs du même type et que j'incrémente un pointeur d'un autre type de cette différence, il n'y a pas de conversions de taille.

 

L'arithmétique sur les pointeurs, c'est pour aider l'indexation.


Message édité par Un Programmeur le 18-01-2011 à 20:34:54

---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed