problème de compréhension avec les pointeurs

Voir le sujet précédent Voir le sujet suivant Aller en bas

problème de compréhension avec les pointeurs

Message  savinois le Lun 22 Juin 2009 - 10:17

bonjour, ... mes incompréhensions se trouvent ci dessous
Code:
// codeblocks802-ubuntu804
#include <stdio.h>
#include <stdlib.h>

int main() {

void *ptr = NULL;
void *up;
float *pf = NULL;
int *p_int = NULL ;
float f[10];
int a;

printf ("adresse de ptr] : %p\n", ptr);//nil
printf ("adresse de up  : %p\n", up);//aléatoire
printf ("adresse de pf ] : %p\n", pf);//nil
printf ("adresse de f    : %p\n", f);//ok
printf ("adresse de f[0] : %p\n", &f[0]);//ok
printf ("adresse de &f  : %p\n\n", &f);//ok

printf("\n");
up=&f[0]; // ok
printf ("adresse de up  : %p\n", up);//ok
// ligne 23
*(float *)up =5.43; // ok
// printf ("contenu de up : %f\n", *up);
// main.c|21|attention : dereferencing «void *» pointer|
// main.c|21|erreur: utilisation invalide d'expression void|
// ||=== Build finished: 2 errors, 0 warnings ===|
/* pourtant à la ligne 24 j'avais casté! Le cast ne serait il temporaire c.a.d valable que pour le temps de l'affectation? Une fois l'affectation réalisée le pointeur up serait à nouveau du type void mais contenant malgré tout une valeur!! Mais alors comment accéder à cet te valeur sinon par un autre pointeur (pf) qui recevrait l'adresse de up! Y aurait il une autre solution pour accéder à up? */
printf ("contenu de up  : %f\n", *(float *)up);
/* je viens de trouver : il faut recaster à nouveau. Le raisonnement est il correct? */

printf("\n");
pf=up;
printf ("adresse de pf    : %p\n", pf);//ok
printf ("contenu de pf    : %f\n\n", *pf);//ok

// test pour un int
printf ("adresse de a    : %p\n", &a);//ok
printf("ptr reçoit adresse de a\n\n");
ptr = (int *) &a;
p_int=ptr ;
printf ("adresse de ptr  : %p\n", ptr);
printf ("adresse de p_int : %p\n", p_int);

*(int *)ptr=128 ;
printf ("contenu de ptr  : %d\n", *(int *)ptr);
printf ("contenu de p_int : %d\n\n", *p_int);

//ligne 53
ptr = (char *) 'c';// ptr reçoit l'adresse 0x63
printf ("adresse de ptr  : %p\n", ptr);
printf ("contenu de ptr  %c\n", *(char *)ptr);
/* ici lors de d'éxécution je recois un segmentation fault ?? pourquoi alors que le compilateur accepte bizzarement l'adresse 0x63 !
return 0;
}

retraité, je commence l'apprentissage du langage c. Excusez mon ignorance. J'ai mis les messages du compilateur à l'endroit des problèmes.
D'avance merci de vos remarques */


Dernière édition par -ed- le Sam 27 Juin 2009 - 10:49, édité 1 fois (Raison : Ajout des balises de code. Merci de le faire à l'avenir ...)

savinois

Messages : 1
Date d'inscription : 22/06/2009

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

désolé pour le retard, j'ai eu une semaine agitée...

Message  -ed- le Sam 27 Juin 2009 - 10:44

savinois a écrit:bonjour, ... mes incompréhensions se trouvent ci dessous
<...>
/* ici lors de d'éxécution je recois un segmentation fault ?? pourquoi alors que le compilateur accepte bizzarement l'adresse 0x63 !
return 0;
}
Merci d'utiliser les balises de code...

Un meilleure réglage du compilateur

http://www.bien-programmer.fr/codage.htm#cfg_compilo

fait apparaitre un certain nombre de défauts :
Code:


-------------- Build: Debug in hello ---------------

Compiling: main.c
Linking console executable: bin\Debug\hello.exe
C:\dev\hello\main.c:4: warning: function declaration isn't a prototype
C:\dev\hello\main.c: In function `main':
C:\dev\hello\main.c:15: warning: void format, float arg (arg 2)
C:\dev\hello\main.c:16: warning: void format, float arg (arg 2)
C:\dev\hello\main.c:17: warning: void format, float arg (arg 2)
C:\dev\hello\main.c:18: warning: void format, different type arg (arg 2)
C:\dev\hello\main.c:35: warning: void format, float arg (arg 2)
C:\dev\hello\main.c:39: warning: void format, different type arg (arg 2)
C:\dev\hello\main.c:44: warning: void format, different type arg (arg 2)
C:\dev\hello\main.c:7: warning: 'up' might be used uninitialized in this function
Output size is 19.89 KB
Process terminated with status 0 (0 minutes, 1 seconds)
0 errors, 9 warnings
Correction et commentaires :
Code:

#include <stdio.h>
#include <stdlib.h>

/* -ed- ajoute void, car la fonction n'a pas de parametres */
int main (void)
{

  void *ptr = NULL;

  void *up;
/* -ed- ATTENTION : pointeur non initialisé */

  float *pf = NULL;
  int *p_int = NULL;
  float f[10];
  int a;

  printf ("adresse de ptr] : %p\n", ptr); /* nil */
/* -ed- le commentaire est faux. Si on veut l'adresse de ptr, c'est &ptr.
        ptr exprime le contenu de ptr (une adresse) qui est ici, l'adresse invalide
        (nil ou NULL) . */

  printf ("adresse de up  : %p\n", up); /* aléatoire */
/* -ed- c'est pas 'aleatoire', mais indéfini, ce qui peut provoquer une erreur
        dès la lecture de la variable (si la valeur est une 'Trap representation').
        Le comportement est indéfini.

        Ce problème est signalé par le compilateur.

        Et ce n'est toujours pas l'adresse de up...
*/

  printf ("adresse de pf ] : %p\n", (void *) pf); /* nil */
/* -ed- Le commentaire est faux. Si on veut l'adresse de pf, c'est &pf.
        pf exprime le contenu de p (qui se trouve être une adresse) f.
*/

  printf ("adresse de f    : %p\n", (void *) f); /* ok */
  printf ("adresse de f[0] : %p\n", (void *) &f[0]); /* ok */
  printf ("adresse de &f  : %p\n\n", (void *) &f); /* ok */
  printf ("\n");

  up = &f[0];                  /* ok */
  /*-ed- OK. up contient maintenant une adtesse valide */

  printf ("adresse de up  : %p\n", up); /* ok */
/* ligne 23 */

  *(float *) up = 5.43;        /* ok */
/* -ed- OK, parce que up est de type void *. Mais personnellement, j'utilise
        un pointeur intermédiare du bon type. Je n'aime pas les casts... */

/* printf ("contenu de up : %f\n", *up); */
/* main.c|21|attention : dereferencing «void *» pointer| */
/* main.c|21|erreur: utilisation invalide d'expression void| */
/* ||=== Build finished: 2 errors, 0 warnings ===| */
/* pourtant à la ligne 24 j'avais casté! Le cast ne serait il temporaire
c.a.d valable que pour le temps de l'affectation? Une fois l'affectation
réalisée le pointeur up serait à nouveau du type void mais contenant malgré
tout une valeur!! Mais alors comment accéder à cet te valeur sinon par un autre
pointeur (pf) qui recevrait l'adresse de up! Y aurait il une autre solution pour
accéder à up? */

/* -ed- Oui, absolument. C'est pour ça que j'utilise un pointeur 'relais' du bon type...
*/
  {
      float *upf = up;
      *upf = 5.43;
      printf ("valeur pointee par up (et upf) : %f\n", *upf);
  }
/* -ed- NOTA : j'ai corrige le commentaire ... */

  printf ("contenu de up  : %f\n", *(float *) up);
/* je viens de trouver : il faut recaster à nouveau. Le raisonnement est il correct? */
/* -ed- oui, mais c'est lourdingue. Dans la pratique on utilise un pointeur relais... */

  printf ("\n");
  pf = up;
  printf ("contenu de pf            : %p\n", (void *) pf); /* ok */
  printf ("valeur pointee par pf    : %f\n\n", *pf); /* ok */

/* test pour un int */
  printf ("adresse de a    : %p\n", (void *) &a); /* ok */
  printf ("ptr reçoit adresse de a\n\n");
/* -ed-
  ptr = (int *) &a;

  le cast est inutile. a doit être de type int. &a est donc bien de type int * */
  ptr = &a;

  p_int = ptr;
  printf ("contenu de ptr  : %p\n", ptr);
  printf ("contenu de p_int : %p\n", (void *) p_int);

  *(int *) ptr = 128;
  printf ("valeur pointee par ptr  : %d\n", *(int *) ptr);
  printf ("valeur pointee par p_int : %d\n\n", *p_int);

/* ligne 53 */
  /* ptr = (char *) 'c'; *//* ptr reçoit l'adresse 0x63 */
/* -ed- ca n'a aucun sens. Il faut utiliser la même logique. */
  {
      char b;
      ptr = &b;
      *(char *) ptr = 'c';

      printf ("contenu de ptr        : %p\n", ptr);
      printf ("valeur pointee par ptr : %c\n", *(char *) ptr);

  }

/* ici lors de d'éxécution je recois un segmentation fault ?? pourquoi alors que le compilateur accepte bizzarement l'adresse 0x63 ! */
  return 0;
}
Sortie :
Code:

adresse de ptr] : 00000000
adresse de up  : 7FFD4000
adresse de pf ] : 00000000
adresse de f    : 0022FF10
adresse de f[0] : 0022FF10
adresse de &f  : 0022FF10


adresse de up  : 0022FF10
valeur pointee par up (et upf) : 5.430000
contenu de up  : 5.430000

contenu de pf            : 0022FF10
valeur pointee par pf    : 5.430000

adresse de a    : 0022FF0C
ptr reþoit adresse de a

contenu de ptr  : 0022FF0C
contenu de p_int : 0022FF0C
valeur pointee par ptr  : 128
valeur pointee par p_int : 128

contenu de ptr        : 0022FF0B
valeur pointee par ptr : c

Process returned 0 (0x0)  execution time : 0.092 s
Press any key to continue.
A lire d'urgence :

http://www.bien-programmer.fr/notes.htm#pointeurs

Poser des questions si nécessaires.

_________________
C is a sharp tool !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum