Академический Документы
Профессиональный Документы
Культура Документы
4 novembre 2011
pr esent e par
Matthieu Finiasz
Structures en C
Quest-ce quun structure en C ? Les structures sont une fa con de d enir de nouveaux types en C : des types compos es de plusieurs el ements dautres types, chaque sous el ement a un nom accessible avec .
1 2 3 4
// attention au ;
struct complex complex_add(struct complex a, struct complex b) { struct complex res; // d eclaration res.re = a.re + b.re; // acc` es ` a la partie re res.im = a.im + b.im; return res; // valeur de retour }
Quest-ce quun structure en C ? Taper struct avant le type ` a chaque fois est un peu lourd on utilise en g en eral un typedef cr ee un alias
1 2 3 4 5
struct complex_st { double re; double im; }; typedef struct complex_st complex ;
Repr esentation en m emoire Une structure est un objet compos ee de plusieurs parties cest la m eme chose en m emoire. On peut aussi utiliser sizeof sur une structure renvoie le nombre doctet n ecessaire ` a son stockage (au moins la somme des sizeof de ses parties).
Pile Tas
.re 3.4 s3 .im -5.2 ??? .re 1.5 s2 .im 3.2 ??? s1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// lignes/colonnes // coefficients
typedef struct { unsigned int epoch_sec; int utc_offset; } date ; typedef struct { char * nom; char * prenom; int sexe; int promo; } eleve ;
Structures et fonctions Les structures sont g er ees comme des types natifs : elles sont donc recopi ees quand on les passe en argument, elles peuvent etre des variables locales lib er ees automatiquement en n de fonction. Cest pratique, mais cest assez cher pour les petites structures recopier nest pas trop cher, pour des grosses structures, mieux vaut utiliser des pointeurs. Attention, seul le contenu de la structure est recopi e, pas ce sur quoi elle pointe !
1 2 3 4
Structures et fonctions
Exemple en recopiant typedef struct { double re, im; } complex; complex cplx_add(complex a, complex b) { complex res; res.re = a.re + b.re; res.im = a.im + b.im; return res; } int main() { complex a = {1.5, 2.2}; complex b = {-2, 3.5}; a = cplx_add(a,b); return 0; }
Pile
2 3 4 5 6 7 8 9 10 11
.re -2.0 b .im 3.5 ??? .re a .im 1.5 2.2 ???
12
main
13 14 15 16 17
Structures et fonctions
Exemple en recopiant typedef struct { double re, im; } complex; complex cplx_add(complex a, complex b) { complex res; res.re = a.re + b.re; res.im = a.im + b.im; return res; } int main() { complex a = {1.5, 2.2}; complex b = {-2, 3.5}; a = cplx_add(a,b); return 0; }
Pile
.re res .im .re b .im .re a .im ??? ??? ??? ??? ??? ???
line 15
2 3 4 5
cplx_add main
6 7 8 9 10 11 12 13 14 15 16 17
.re -2.0 b .im 3.5 ??? .re a .im 1.5 2.2 ???
Structures et fonctions
Exemple en recopiant typedef struct { double re, im; } complex; complex cplx_add(complex a, complex b) { complex res; res.re = a.re + b.re; res.im = a.im + b.im; return res; } int main() { complex a = {1.5, 2.2}; complex b = {-2, 3.5}; a = cplx_add(a,b); return 0; }
Pile
.re res .im ??? ??? .re -2.0 b .im 3.5 ??? .re 1.5 a .im 2.2 ???
line 15
2 3 4 5
cplx_add main
6 7 8 9 10 11 12 13 14 15 16 17
.re -2.0 b .im 3.5 ??? .re a .im 1.5 2.2 ???
Structures et fonctions
Exemple en recopiant typedef struct { double re, im; } complex; complex cplx_add(complex a, complex b) { complex res; res.re = a.re + b.re; res.im = a.im + b.im; return res; } int main() { complex a = {1.5, 2.2}; complex b = {-2, 3.5}; a = cplx_add(a,b); return 0; }
Pile
.re res .im -0.5 ??? .re -2.0 b .im 3.5 ??? .re 1.5 a .im 2.2 ???
line 15
2 3 4 5
cplx_add main
6 7 8 9 10 11 12 13 14 15 16 17
.re -2.0 b .im 3.5 ??? .re a .im 1.5 2.2 ???
Structures et fonctions
Exemple en recopiant typedef struct { double re, im; } complex; complex cplx_add(complex a, complex b) { complex res; res.re = a.re + b.re; res.im = a.im + b.im; return res; } int main() { complex a = {1.5, 2.2}; complex b = {-2, 3.5}; a = cplx_add(a,b); return 0; }
Pile
.re res .im -0.5 5.7 ??? .re -2.0 b .im 3.5 ??? .re 1.5 a .im 2.2 ???
line 15
2 3 4 5
cplx_add main
6 7 8 9 10 11 12 13 14 15 16 17
.re -2.0 b .im 3.5 ??? .re a .im 1.5 2.2 ???
Structures et fonctions
Exemple en recopiant typedef struct { double re, im; } complex; complex cplx_add(complex a, complex b) { complex res; res.re = a.re + b.re; res.im = a.im + b.im; return res; } int main() { complex a = {1.5, 2.2}; complex b = {-2, 3.5}; a = cplx_add(a,b); return 0; }
Pile
.re res .im -0.5 5.7 ??? .re -2.0 b .im 3.5 ??? .re 1.5 a .im 2.2 ???
line 15
2 3 4 5
cplx_add main
6 7 8 9 10 11 12 13 14 15 16 17
.re -2.0 b .im 3.5 ??? .re a .im -0.5 5.7 ???
Structures et fonctions
Exemple en recopiant typedef struct { double re, im; } complex; complex cplx_add(complex a, complex b) { complex res; res.re = a.re + b.re; res.im = a.im + b.im; return res; } int main() { complex a = {1.5, 2.2}; complex b = {-2, 3.5}; a = cplx_add(a,b); return 0; }
Pile
2 3 4 5 6 7 8 9 10 11
.re -2.0 b .im 3.5 ??? .re a .im -0.5 5.7 ???
12
main
13 14 15 16 17
Structures et fonctions
Passage par adresse
Pour eviter la recopie de structures on utilise le passage par adresse on ne recopie alors quune adresse m emoire la taille du pointeur ne d epend pas de la taille de la structure. En g en eral on pr ef` ere aussi stocker les structures dans le tas : on d eclare uniquement les pointeurs en variables locales, on alloue les structures avec malloc, il faut ensuite les lib erer avec free. Avec des pointeurs uniquement, le code est un peu plus long ` a ecrire, mais on ne recopie quune adresse on peut gagner beaucoup en ecacit e. Pour acc eder ` a une composante il faut dabord suivre un pointeur (*a).re est un peu lourd, la notation a->re est equivalente (et plus lisible).
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
??? main
b a
???
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
??? main
b a .re .im ??? ???
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
.re .im
??? ???
main
b a
.re .im
??? ???
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
main
b a
.re .im
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
main cplx_add
res b a
line 15
???
.re .im
b a
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas ???
main cplx_add
res b a
line 15
b a
.re .im
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
.re .im
main cplx_add
res b a
line 15
b a
.re .im
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
main cplx_add
res b a
line 15
b a
.re .im
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
main cplx_add
res b a
line 15
b a
.re .im
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
.re -0.5 .im ??? 5.7 .re -2.0 .im ??? 3.5
main
b a
.re .im
Structures et fonctions
Exemple avec passage par adresse
1 2 3 4 5 6 7 8
complex* cplx_add(complex* a, complex* b) { complex* res; res = malloc(sizeof(complex)); res->re = a->re + b->re; res->im = a->im + b->im; return res; }
9 10 11 12 13 14 15 16
int main() { complex *a, *b; a = malloc(sizeof(complex)); b = malloc(sizeof(complex)); a->re=1.5; a->im=2.2; b->re=-2; b->im=3.5; a = cplx_add(a,b); free(a); free(b); }
Pile
Tas
.re -0.5 .im ??? 5.7 .re -2.0 .im ??? 3.5
main
b a
.re .im
mmoire perdue
Tableaux de structures Il est aussi possible de faire des tableaux de structures soit des tableaux simples :
1 2 3
complex** tab; tab = (complex** ) malloc(10*sizeof(complex* )); for (i=0; i<10; i++) { tab[i] = (complex* ) malloc(sizeof(complex )); } tab[5]->re = 2;
Il faut bien regarder si tab[5] est une structure ou un pointeur et utilise le bon symbole . ou ->
Structure r ecursives Il est aussi possible de d enir des structure r ecursives pas des structures qui contiennent un el ement de leur type probl` eme pour conna tre la taille eective de la structure... mais contenant un pointeur vers une structure du m eme type.
1 2 3 4
On ne peut pas encore utiliser le nom du typedef ` a ce moment obligatoire davoir un nom de structure. Nous reverrons cela pour les listes cha n ees, arbres... (cf. prochains cours)
Biblioth` eques et modularit e Une structure sert ` a repr esenter un type de donn ees soit tr` es sp ecique ne sert qu` a un programme, soit plus g en eral peut resservir dans dautres programmes. Quand on d enit une structure, on veut en g en eral aussi d enir : une fonction dinitialisation, une fonction dachage, une fonction de destruction (lib eration de la m emoire)... on ne veut pas tout r ecrire ` a chaque fois. Il sera plus facile de r eutiliser cela dans une biblioth` eque plut ot que de tout ecrire dans un seul chier, faire un chier qui contient toutes les fonctions propres ` a la biblioth` eque, et un chier ` a c ot e avec le main et autres fonctions sp eciques.
Ecriture dune biblioth` eque Une biblioth` eque peut simplement etre un chier .c ` a inclure en d ebut de programme oblige lutilisateur ` a tout lire pour conna tre les fonctions, le code de la biblioth` eque est recompil e` a chaque compilation. Pour plus de lisibilit e on fait en g en eral deux chiers : un chier .c qui contient le code des fonctions, un chier .h qui ne contient que les en-t etes de fonctions seul ce chier est inclus et sut pour utiliser la biblioth` eque. Le chier .c doit quand m eme etre inclus ` a la compilation : > gcc -Wall prog.c lib.c -o prog et prog.c doit contenir #include "lib.h"
cplx.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14
struct cplx_st { double re,im; }; typedef struct cplx_st* cplx ; cplx cplx_init(double re, double im); cplx cplx_add(cplx a, cplx b); cplx cplx_mul(cplx a, cplx b); cplx cplx_inv(cplx a); double cplx_norm(cplx a); void cplx_print(cplx a); void cplx_free(cplx a);
#include "cplx.h" cplx cplx_init(double re, double im){ cplx res = malloc(sizeof(struct cplx_st )); if (res != NULL) { res->re = re; res->im = im; } return res; } ... void cplx_print(cplx a) { printf("%f + i%f",a->re,a->im); } void cplx_free(cplx a) { free(a); }
#include "cplx.h" int main() { cplx a,b,c; a = cplx_init(1.5, 3.2); b = cplx_init(-2, 2.5); c = cplx_add(a, b); cplx_print(c); printf("\n"); cplx_free(a); cplx_free(b); cplx_free(c); return 0; }
Ce quil faut retenir de ce cours Les structures sont un outil centrale en C permettent de regrouper des variables, simplient la manipulation de donn ees complexes. Les structures sont souvent tr` es ecaces attention ` a ne pas faire trop de recopies inutiles, en g en eral on les utilise toujours avec des pointeurs la notation -> existe pour une raison ! Les structures ne remplacent pas des vrais objets comme en C++, java ou OCaml : pas de m ethodes, dh eritage... Elles servent surtout pour les structures de donn ees : matrices, listes cha n ees, arbres, graphes...