Cette page contient une liste de quelques erreurs classiques que l'on peut faire en programmant en C. Un des gros problèmes de la programmation (en générale, mais surtout en C) est qu'on peut avoir des programmes faux qui ont l'air de marcher mais vont planter dans certaines situations (dans un environement different ou après un long moment).
De plus je vous recommande de définir une macro ou une constante pour la taille du tableau (10).
Il y a deux fautes que beaucoup d'étudiants font, surtout s'ils savent
programmer en Java :
Explications. 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 mémoire :
Notes :
La variable n n'est pas crée sur une pile, mais ailleurs, dans la section « static storage » (aussi appelée « initialized data segment ») qui est une zone mémoire en lecture seulement (« read-only »).
En fait il n'y a pas une pile par fonction, mais une seule pile par programme (une pile par thread en fait). Quand une pile est alouée, elle est simplement ajoutée à la fin de la précédente. Quand une pile est désalouée, les données sont encore accessibles, jusqu'à qu'une autre pile vient se mettre par-dessus.
Les parametres des fonctions sont passés sur la pile. Passer directement des structures (au lieu de pointeurs), provoque donc des copies vers/depuis les différentes piles.
Voici maintenant un code C qui crée un rectangle.
typedef struct _rectangle { int width; int height; } rectangle;
Voici deux premières versions contiennent des erreurs :
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 fonctionne correctement) effectue en effet une copie de la structure au niveau du return.
Tentative de correction en utilisant des pointeurs :
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); }
C'est pire qu'avant car ce code est carrément faux ! Il retourne en effet l'adresse d'une variable locale... On court tout droit au «segmentation fault»
Voici maintenant deux solutions qui sont correctes :
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) ! ... }
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); }Notez que dans cette dernière solution create perd de son sens premier car en tout rigueur ne crée plus rien du tout. Cette dernière fonction devrait donc plutôt s'appeler init ou quelque chose comme ça.