Vous êtes sur la page 1sur 35

IN 101 - Cours 08

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

struct complex { double re; double im; };

// attention au ;

Les structures sutilisent ensuite exactement comme les types natifs


1 2 3 4 5 6 7

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 ;

On peut aussi utiliser le typedef directement ` a la d enition :


1 2 3 4

typedef struct { double re; double im; } complex ;

La structure sutilise alors directement avec complex res;

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

.re -2.1 .im ??? 2.5

Quelques exemples de structures

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

typedef struct { unsigned int l,c; double * * coef; } matrix ;

// 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

struct table { int size; int * tab; };

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

.re -2.0 .im ??? 3.5

main

b a

.re .im

1.5 2.2 ???

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

???
.re .im

.re -2.0 .im ??? 3.5

b a

1.5 2.2 ???

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

.re -2.0 .im ??? 3.5

b a

.re .im

1.5 2.2 ???

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

??? ??? .re -2.0 .im ??? 3.5

main cplx_add

res b a
line 15

b a

.re .im

1.5 2.2 ???

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

main cplx_add

res b a
line 15

.re -2.0 .im ??? 3.5

b a

.re .im

1.5 2.2 ???

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

main cplx_add

res b a
line 15

.re -2.0 .im ??? 3.5

b a

.re .im

1.5 2.2 ???

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

1.5 2.2 ???

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

1.5 2.2 ???

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 )); tab[5].re = 2;

soit des tableaux de pointeurs :


1 2 3 4 5 6

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

typedef struct cell_st { int val; struct cell_st* next; } cell ;

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)

Structures et biblioth` eques

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"

Exemple de biblioth` eque


Nombres complexes

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);

Exemple de biblioth` eque


Nombres complexes cplx.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#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); }

Exemple de biblioth` eque


Nombres complexes prog.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

#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; }

Compiler avec : gcc -Wall -O3 cplx.c prog.c -o prog

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...