[C] pointeurs de pointeurs [RESOLU]

pointeurs de pointeurs [RESOLU] [C] - C - Programmation

Marsh Posté le 25-04-2011 à 09:36:49    

Bonjour,
 
J'étais en train d'écrire un petit programme de test pour bien comprendre les principes des pointeurs en C en i686 en gcc, tout se compile bien, les données sont lisibles dans les fonctions, mais plus à leur sortie, je ne comprend pas mon erreur.
 
Pouvez-vous me corriger ce code ?
Merci.
 
settings.h

Code :
  1. #ifndef __SETTINGS_H__
  2. #define __SETTINGS_H__
  3. typedef struct __test {
  4.     int  a;
  5.     char b;
  6.     char c[20];
  7.     char *d;
  8. } _TEST;
  9. void setinit(_TEST *);
  10. #endif


 
settings.c

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "settings.h"
  5. void setinit(_TEST *test)
  6. {
  7. test=malloc(sizeof(_TEST));
  8. if (test != NULL)
  9. {
  10.  test->a=34;
  11.  test->b='B';
  12.  sprintf(test->c, "%s", "test c ok" );
  13.  test->d=malloc((strlen("test d ok" ) + 1) * sizeof(char));
  14.  if (test->d != NULL)
  15.   test->d="test d ok";
  16.  printf("setinit [%d]\n", test->a);
  17.  printf("setinit [%c]\n", test->b);
  18.  printf("setinit [%s]\n", test->c);
  19.  printf("setinit [%s]\n", test->d);
  20. }
  21. }


 
main.h

Code :
  1. #ifndef __MAIN_H__
  2. #define __MAIN_H__
  3. typedef struct __essai {
  4.     int  a;
  5.     char b;
  6.     char c[20];
  7.     char *d;
  8. } _ESSAI;
  9. #endif


 
main.c

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "main.h"
  5. #include "settings.h"
  6. _TEST  *test;
  7. _ESSAI *essai;
  8. void maininit(_ESSAI *essai)
  9. {
  10. essai=malloc(sizeof(_ESSAI));
  11. if (essai != NULL)
  12. {
  13.  essai->a=12;
  14.  essai->b='b';
  15.  sprintf(essai->c, "%s", "essai c ok" );
  16.  essai->d=malloc((strlen("essai d ok" ) + 1) * sizeof(char));
  17.  if (essai->d != NULL)
  18.   essai->d="essai d ok";
  19.  printf("maininit [%d]\n", essai->a);
  20.  printf("maininit [%c]\n", essai->b);
  21.  printf("maininit [%s]\n", essai->c);
  22.  printf("maininit [%s]\n", essai->d);
  23. }
  24. }
  25. int main()
  26. {
  27. setinit(test);
  28. maininit(essai);
  29. if (test != NULL)
  30. {
  31.  printf("test  [%d]\n", test->a);
  32.  printf("test  [%c]\n", test->b);
  33.  printf("test  [%s]\n", test->c);
  34.  printf("test  [%s]\n", test->d);
  35. }
  36. if (essai != NULL)
  37. {
  38.  printf("essai [%d]\n", essai->a);
  39.  printf("essai [%c]\n", essai->b);
  40.  printf("essai [%s]\n", essai->c);
  41.  printf("essai [%s]\n", essai->d);
  42. }
  43. free(essai);
  44. essai=NULL;
  45. free(test);
  46. test=NULL;
  47.     return(0);
  48. }


 
Le résultat d'exécution donne ceci :

Code :
  1. setinit [34]
  2. setinit [B]
  3. setinit [test c ok]
  4. setinit [test d ok]
  5. maininit [12]
  6. maininit [b]
  7. maininit [essai c ok]
  8. maininit [essai d ok]


 
Il manque donc bien les lignes d'impression du main.
 
Merci pour votre aide


Message édité par Noobs69 le 25-04-2011 à 18:18:30
Reply

Marsh Posté le 25-04-2011 à 09:36:49   

Reply

Marsh Posté le 25-04-2011 à 10:04:49    

Si je comprends bien (tu aurais pu faire plus court comme test :o)
 
Tu espères pouvoir modifier tes pointeurs test et essai juste en les passant dans une fonction qui les assigne au résultat de malloc ?
 
Ca ne peut pas marcher pour une raison simple: Quand tu fais passer un paramètre à une fonction, cette fonction va en réalité travailler avec une copie de ce paramètre. A la fin de ta fonction, ce paramètre va donc être détruit et évidemment tu auras donc perdu le pointeur que t'a retourné malloc.
 
Si tu voulais pouvoir modifier ce pointeur "a distance", il faudrait que tu fasses passer en paramètre l'adresse du pointeur (donc setinit(&essai) et maininit(&test)), que tu modifies bien évidemment le prototype de ces fonctions en conséquence et une fois cela fait, tu aurais alors un pointeur sur pointeur.
 
Ce que ça change ? Tu pourras alors modifier l'adresse du pointeur essai et test en faisant une assignation toute simple comme *essai = NULL; ou *test = malloc() ou ce que tu veux :D
 
J'espère avoir répondu à ta question :jap:


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 25-04-2011 à 10:32:17    

Merci mais je n'arrive pas à compiler correctement à présent.
 
J'ai fait ça comme modifs :
 
 
settings.h

Code :
  1. ...
  2. void setinit(_TEST **);
  3. ...


 
settings.c

Code :
  1. ...
  2. void setinit(_TEST **test)
  3. {
  4. *test=malloc(sizeof(_TEST));
  5. if (test != NULL)
  6. {
  7.  test->a=34;
  8. ...


 
main.c

Code :
  1. ...
  2. void maininit(_ESSAI **essai)
  3. {
  4. *essai=malloc(sizeof(_ESSAI));
  5. if (essai != NULL)
  6. {
  7.  essai->a=12;
  8. ...
  9. int main()
  10. {
  11. setinit(&test);
  12. maininit(&essai);
  13. ...


 
Je vois bien que l'erreur est dans l'affectation à présent mais je ne vois pas comment écrire ça correctement.


Message édité par Noobs69 le 25-04-2011 à 10:35:37
Reply

Marsh Posté le 25-04-2011 à 10:41:58    

Pour te simplifier les choses (tu pourras comprendre après :D): Tu as bien modifié le prototype, par contre dans ta fonction à chaque fois que tu as "test" ou "essai" il faut qu tu remplaces par *test et par *essai (donc tu mets une étoile chaque fois, ce n'est pas l'adresse du pointeur de pointeur que tu veux modifier mais l'adresse du premier pointeur) :D

 

Donc par exemple, tu remplaces if (essai != NULL) par if (*essai != NULL) etc ...


Message édité par WiiDS le 25-04-2011 à 10:42:12

---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 25-04-2011 à 10:45:37    

Je creuse pour comprendre pourtant !!
 
Ca fonctionne pour malloc et le test, mais je ne comprend pas la syntaxe à adopter pour l'affectation :
 

Code :
  1. essai->a=12;   //???
  2.  *essai->a=12;  //???
  3.  essai[0]->a=12; //CA, ça compile, mais j'y crois pas du tout !!
  4.  *essai->b='b';


 
Je me prend des :
 error: request for member `a' in something not a structure or union
 


Message édité par Noobs69 le 25-04-2011 à 10:47:11
Reply

Marsh Posté le 25-04-2011 à 11:04:07    

Tu as essayé (*essai)->a=12; ? Faut faire gaffe à l'endroit ou on met les *, faut pas déréférencer n'importe quoi :o

 

Parce que je pense qu'en faisant *essai->a = 12, ton compilateur doit comprendre essai->*a = 12


Message édité par WiiDS le 25-04-2011 à 11:04:45

---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 25-04-2011 à 11:09:14    

J'essaye ça de suite !!
 
Moi, j'en étais là pour contourner :
 

Code :
  1. {
  2. _ESSAI *tmp;
  3. tmp=malloc(sizeof(_ESSAI));
  4. if (tmp != NULL)
  5. {
  6.  tmp->a=12;
  7.  tmp->b='b';
  8.  sprintf(tmp->c, "%s", "essai c ok" );
  9.  tmp->d=malloc((strlen("essai d ok" ) + 1) * sizeof(char));
  10.  if (tmp->d != NULL)
  11.   tmp->d="essai d ok";
  12.  printf("maininit [%d]\n", tmp->a);
  13.  printf("maininit [%c]\n", tmp->b);
  14.  printf("maininit [%s]\n", tmp->c);
  15.  printf("maininit [%s]\n", tmp->d);
  16. }
  17. *essai=tmp;


 
Merci de ton aide précieuse et claire, j'avance vite avec une aide qui explique et ne met pas des commentaires lapidaires et inutiles comme souvent sur les forums, j'apprécie.

Reply

Marsh Posté le 25-04-2011 à 11:17:05    

Ca fonctionne !!!
 
Et ton analyse du préprocesseur est correcte, il comprend l'inverse, belle blague celle-là, merci grandement de ta pédagogie.
 
Je mets tout au propre et je post ici mon code complet, si ça peut en aider d'autres à "naviguer" dans les pointeurs de pointeurs en C ...
 
settings.h

Code :
  1. #ifndef __SETTINGS_H__
  2. #define __SETTINGS_H__
  3. #include <stdbool.h>
  4. typedef struct __test {
  5.     int  a;
  6.     char b;
  7.     char c[20];
  8.     char *d;
  9. } _TEST;
  10. void setinit(_TEST **);
  11. #endif


 
settings.c

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "settings.h"
  5. void setinit(_TEST **test)
  6. {
  7. *test=malloc(sizeof(_TEST));
  8. if (*test != NULL)
  9. {
  10.  (*test)->a=34;
  11.  (*test)->b='B';
  12.  sprintf((*test)->c, "%s", "test c ok" );
  13.  (*test)->d=malloc((strlen("test d ok" ) + 1) * sizeof(char));
  14.  if ((*test)->d != NULL)
  15.   (*test)->d="test d ok";
  16.  printf("maininit [%d]\n", (*test)->a);
  17.  printf("maininit [%c]\n", (*test)->b);
  18.  printf("maininit [%s]\n", (*test)->c);
  19.  printf("maininit [%s]\n", (*test)->d);
  20. }
  21. }


 
main.h

Code :
  1. #ifndef __MAIN_H__
  2. #define __MAIN_H__
  3. typedef struct __essai {
  4.     int  a;
  5.     char b;
  6.     char c[20];
  7.     char *d;
  8. } _ESSAI;
  9. #endif


 
main.c

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "main.h"
  5. #include "settings.h"
  6. _TEST  *test;
  7. _ESSAI *essai;
  8. void maininit(_ESSAI **essai)
  9. {
  10. *essai=malloc(sizeof(_ESSAI));
  11. if (*essai != NULL)
  12. {
  13.  (*essai)->a=12;
  14.  (*essai)->b='b';
  15.  sprintf((*essai)->c, "%s", "essai c ok" );
  16.  (*essai)->d=malloc((strlen("essai d ok" ) + 1) * sizeof(char));
  17.  if ((*essai)->d != NULL)
  18.   (*essai)->d="essai d ok";
  19.  printf("maininit [%d]\n", (*essai)->a);
  20.  printf("maininit [%c]\n", (*essai)->b);
  21.  printf("maininit [%s]\n", (*essai)->c);
  22.  printf("maininit [%s]\n", (*essai)->d);
  23. }
  24. }
  25. int main()
  26. {
  27. setinit(&test);
  28. maininit(&essai);
  29. if (test != NULL)
  30. {
  31.  printf("test  [%d]\n", test->a);
  32.  printf("test  [%c]\n", test->b);
  33.  printf("test  [%s]\n", test->c);
  34.  printf("test  [%s]\n", test->d);
  35. }
  36. if (essai != NULL)
  37. {
  38.  printf("essai [%d]\n", essai->a);
  39.  printf("essai [%c]\n", essai->b);
  40.  printf("essai [%s]\n", essai->c);
  41.  printf("essai [%s]\n", essai->d);
  42. }
  43. free(essai);
  44. essai=NULL;
  45. free(test);
  46. test=NULL;
  47.     return(0);
  48. }


 
Résultat du code :

Code :
  1. maininit [34]
  2. maininit [B]
  3. maininit [test c ok]
  4. maininit [test d ok]
  5. maininit [12]
  6. maininit [b]
  7. maininit [essai c ok]
  8. maininit [essai d ok]
  9. test  [34]
  10. test  [B]
  11. test  [test c ok]
  12. test  [test d ok]
  13. essai [12]
  14. essai [b]
  15. essai [essai c ok]
  16. essai [essai d ok]


Message édité par Noobs69 le 25-04-2011 à 11:24:45
Reply

Marsh Posté le 25-04-2011 à 11:27:27    

Ca n'existe pas RESOLU sur ce forum ou je vois mal ?

Reply

Marsh Posté le 25-04-2011 à 11:42:27    

:jap:
 
Tu peux éditer le premier post et changer le titre si tu y tiens vraiment, mais effectivement il n'y a pas de politique concernant le titre des sujets :D
 
Bonne continuation :hello:


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 25-04-2011 à 11:42:27   

Reply

Marsh Posté le 25-04-2011 à 12:31:02    

Je vois pas trop ce que tu veux faire, mais si j'avais à utiliser ce type de structure, je procéderais ainsi:
(Bon, à reformater, la page web ayant pas la même notion de tabulations que mon emacs en mode electric-c)

Code :
  1. /* settings.h*/
  2. #ifndef __SETTINGS_H__
  3. #define __SETTINGS_H__
  4. typedef struct {
  5.     int  a;
  6.     char b;
  7.     char c[20];
  8.     char *d;
  9. } TEST;
  10. TEST *test_create_empty(void);
  11. TEST *test_create(int a, char b, char *c, char *d);
  12. bool test_set(TEST *test, int a, char b, char *c, char *d);
  13. void test_print(TEST *test);
  14. #endif


 

Code :
  1. /* settings.c*/
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6. #include "settings.h"
  7. TEST *test_create_empty(void)
  8. {
  9.     TEST *test = malloc(sizeof(TEST));
  10.     if (test) {
  11.         test->a = 0;
  12.         test->b = 0;
  13.         (test->c)[0] = 0;
  14.         test->d = NULL;
  15.     }
  16.     return test;
  17. }
  18. bool test_set(TEST *test, int a, char b, char *c, char *d)
  19. {
  20.     if (test) {
  21.         test->d = malloc((strlen(d) + 1));
  22.         if (test->d) {
  23.             test->a = a;
  24.             test->b = b;
  25.             strncpy(test->c, c, 20);
  26.             strcpy(test->d, d);
  27.             return true;
  28.         }
  29.     }
  30.     return false;
  31. }
  32. TEST *test_create(int a, char b, char *c, char *d)
  33. {
  34.     TEST *test = malloc(sizeof(TEST));
  35.     if (test) {
  36.         test->d = malloc((strlen(d) + 1));
  37.         if (test->d) {
  38.             test->a = a;
  39.             test->b = b;
  40.             strncpy(test->c, c, 20);
  41.             strcpy(test->d, d);
  42.         }
  43.         else {
  44.             free(test);
  45.             test = NULL;
  46.         }
  47.     }
  48.     return test;
  49. }
  50. void test_print(TEST *test)
  51. {
  52.     printf("a: [%d]\nb: [%c]\nc: [%s]\nd: [%s]\n", test->a, test->b, test->c, test->d);
  53. }


Code :
  1. /* main.c*/
  2. #include <stdlib.h>
  3. #include "settings.h"
  4. int main()
  5. {
  6.     TEST  *test = test_create_empty();
  7.     if (test) {
  8.         if (test_set(test, 34, 'B', "test c ok", "test d ok" )) {
  9.             test_print(test);
  10.         }
  11.         free(test);
  12.         return EXIT_SUCCESS;
  13.     }
  14.     return EXIT_FAILURE;
  15. }


In Hope It Helps,
A+,


Message édité par gilou le 25-04-2011 à 13:42:38

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

Sujets relatifs:

Leave a Replay

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