Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1353 connectés 

  FORUM HardWare.fr
  Programmation
  C

  [C] pointeurs de pointeurs [RESOLU]

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C] pointeurs de pointeurs [RESOLU]

n°2071849
Noobs69
Posté le 25-04-2011 à 09:36:49  profilanswer
 

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
mood
Publicité
Posté le 25-04-2011 à 09:36:49  profilanswer
 

n°2071851
WiiDS
20 titres en GC, 0 abandon, 0 DQ
Posté le 25-04-2011 à 10:04:49  profilanswer
 

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
n°2071852
Noobs69
Posté le 25-04-2011 à 10:32:17  profilanswer
 

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
n°2071853
WiiDS
20 titres en GC, 0 abandon, 0 DQ
Posté le 25-04-2011 à 10:41:58  profilanswer
 

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
n°2071854
Noobs69
Posté le 25-04-2011 à 10:45:37  profilanswer
 

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
n°2071858
WiiDS
20 titres en GC, 0 abandon, 0 DQ
Posté le 25-04-2011 à 11:04:07  profilanswer
 

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
n°2071862
Noobs69
Posté le 25-04-2011 à 11:09:14  profilanswer
 

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.

n°2071866
Noobs69
Posté le 25-04-2011 à 11:17:05  profilanswer
 

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
n°2071867
Noobs69
Posté le 25-04-2011 à 11:27:27  profilanswer
 

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

n°2071873
WiiDS
20 titres en GC, 0 abandon, 0 DQ
Posté le 25-04-2011 à 11:42:27  profilanswer
 

: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
mood
Publicité
Posté le 25-04-2011 à 11:42:27  profilanswer
 

n°2071881
gilou
Modérateur
Modzilla
Posté le 25-04-2011 à 12:31:02  profilanswer
 

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é!  --

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  [C] pointeurs de pointeurs [RESOLU]

 

Sujets relatifs
Affectation illicite de pointeurs en assembleur[C] soustraire deux pointeurs
[boost.serialization] Sérialization, templates et pointeurspointeurs dans un conteneur - comment éviter leur destruction ?
Passage d'un tableau de pointeurs de fonctions en argumenttableaux de pointeurs
Structures, pointeurs..affichage?Cas où les références remplacent mal les pointeurs ?
Tableau de pointeurs en c[résolu] parcours d'un char** sans connaitre le nombre de chaines
Plus de sujets relatifs à : [C] pointeurs de pointeurs [RESOLU]


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR