erreurs classiques
Il y a deux fautes que beaucoup d'étudiants font, surtout s'ils savent
programmer en Java:
- Mauvaise utilisation des structures au niveau des fonctions:
Il ne faut jamais passer directement des structures comme type d'entrée ou de sortie d'une fonction; il faut toujours passer par un pointeur sur une structure.
- Mauvaise utilisation des pointeurs dans les fonctions:
Il ne faut jamais retourner (depuis une fonction) un pointeur sur la pile d'une fonction; car cette zone mémoire va disparaître quand la fonction va retourner. (Les variables locales "vivent" sur la pile.)
Petit rappel, soit le code C suivant:
int n=5; int foo() { int b; } int main() { int a; foo(); }
Voici ce qui se passe au niveau de la pile:
- la pile de main est crée. Elle contient entre autre la variable a.
- le code de main est executé.
- main va appeler foo.
- la pile de foo est crée. Elle contient entre autre la variable b.
- le code de foo est executé.
- la pile de foo est détruite. La variable b n'existe plus.
- on revient dans main.
- la pile de main est détruite. La variable a n'existe plus.
Voici maintenant une série de différents code C qui essayent de faire la même chose, créer un "objet" rectangle, mais qui contiennent tous des grosses erreurs:
typedef struct _rectangle { int width; int height; } rectangle;
Code 1 - ne repect pas la première règle
rectangle create(int w, int h) { rectangle r; r.width = w; r.height = h; return r; } int main() { rectangle r1 = create(5, 6); rectangle r2 = create(12, 3); }
Ce code (qui marche) provoque des copies de la structure au niveau du return.
Code 2 - ne respect pas la deuxième règle
rectangle* create(int w, int h) { rectangle r; r.width = w; r.height = h; return &r; } int main() { rectangle* r1 = create(5, 6); rectangle* r2 = create(12, 3); }
Ce code est faux !
Voici donc deux solutions qui sont bonnes:
Solution 1 - create va allouer l'"objet" (sur le heap)
rectangle* create(int w, int h) { rectangle* r = (rectangle*)malloc(sizeof(rectangle)); r->width = w; r->height = h; return r; } int main() { rectangle* r1 = create(5, 6); rectangle* r2 = create(12, 3); // ne pas oublier ensuite de faire free(r1) et free(r2) ! }
Solution 2 - on va allouer rectangle sur la pile, mais de main
void create(rectangle* r, int w, int h) { r->width = w; r->height = h; } int main() { rectangle r1, r2; create(&r1, 5, 6); create(&r2, 12, 3); }