Cours de C                      Types structurés                      Sébastien Paumierpaumier@univ-mlv.fr      Illustrati...
Les structures●   objets regroupant plusieurs données    appelées "champs"●   à définir hors dune fonction●   définition: ...
Les structures●   déclaration dune variable:    struct nom_type nom_var;●   accès aux champs: nom_var.nom_champ           ...
Choix des champs●   on peut mettre tout ce dont le    compilateur connaît la taille●   on ne peut donc pas mettre la struc...
Structures récursives●   mais on peut mettre un pointeur sur la    structure, car la taille des pointeurs est    connue:  ...
Imbrication de structures●   un champ peut être une structure:    struct id {       char firstname[MAX];       char lastna...
Imbrication de structures●   2 structures peuvent sappeler lune    lautre, à condition dutiliser des    pointeurs:        ...
Contraintes sur les structures●   champs organisés dans lordre de leur    déclarations:                         struct foo...
Alignement●   adresse dune structure = adresse de son    premier champ●   pour les autres champs, le compilateur    fait d...
Alignement●    taille variable suivant lordre des     champs:    struct to {                   struct ta {       char a;  ...
Alignementstruct to {                       struct ta {   char a;                           int a;   int b;               ...
Initialisation ●   struct to t={val0,val1,...,valn-1};                       struct to t={a,145,y,u}; ●   seulement lors d...
Opérations●   laffectation fonctionne               int main(int argc,char* argv[]) {                  struct to z={a,145,...
Structures en paramètres●   les structures sont passées par valeur!    –   non modifiables    –   peuvent occuper beaucoup...
Structures en paramètres  struct array {                 struct array {     int t[100000];                 int t[100000]; ...
Structures en paramètres●   passage dadresse =     –   gain de temps     –   gain despace sur la pile     –   on peut modi...
Retourner une structure●   on peut, mais cest une opération de    copie sur la pile●   mêmes problèmes que pour le passage...
Les unionsunion toto {                         zone mémoire que lon     type1 nom1;         peut voir soit comme un     ty...
Les unions●   taille = taille du plus grand champ●   au programmeur de savoir quel champ    doit être utilisé    union tot...
Les unions●   utiles quand on doit manipuler des    informations exclusives les unes des    autres              union stud...
Unions complexes●   on peut mettre des structures    (anonymes) dans les unions               union color {               ...
Quel(s) champ(s) utiliser ?●   encapsulation dans une structure avec    un champ dinformation                 struct color...
Les énumérations●   enum nom {id0,id1,...,idn-1};●   si on a une variable de type enum nom,    elle pourra prendre les val...
Les énumérations●   valeurs de type int●   par défaut, commencent à 0 et vont de 1    en 1●   on peut les modifier        ...
Les énumérations●   on peut avoir plusieurs fois la même    valeur                        enum color {                    ...
Contrôles des valeurs●   contrairement aux espoirs du    programmeur, pas de contrôle!                  enum gender {male=...
Contrôles des valeurs  ●   seul contrôle: avec -Wall, gcc indique sil      manque des cas dans un switch (quand il      ny...
Déclaration de constantes●   si on veut juste déclarer des constantes,    on peut utiliser une énumération    anonyme    e...
Combinaison union/enum●   quand on utilise une union, cest plus    propre de décrire les alternatives avec    une énumérat...
typedef●   typedef type nom;●   permet de donner un nom à un type,    simple ou composé●   pratique pour éviter de recopie...
typedef●   pas de nouveaux types●   seulement des synonymes    interchangeables                  struct array {           ...
typedef●   pour les types structurés, deux modes de    définition:enum cell_type {EMPTY,BONUS,MALUS,   typedef enum {EMPTY...
Les listes●   application: coder une liste chaînée de    noms de couleurs●   utilisons une structure pour représenter    u...
Les listes●   la mémoire est simulée par un tableau de    telles structures:              /* The cell array that represent...
Les listes●   pour gérer la mémoire, il faut savoir    quelles cellules sont disponibles●   astuce: utilisons une valeur s...
Les listes●   il faut savoir allouer et désallouer:    /**      * Returns the index of the first free cell, or NOTHING if ...
Les listes●   on peut maintenant ajouter une couleur    en tête de liste:/**  * Adds a cell representing the given color a...
Les listes●   on veut pouvoir afficher la liste:                /**                  * Prints the given list.             ...
Les listes●   enfin, il faut pouvoir libérer une liste    entière:                      /**                        * Frees...
Les listes●   on peut maintenant tester notre    bibliothèque:    #include <stdio.h>    #include "color_list.h"    int mai...
Les listes●   bug si on essaie dafficher la liste après    lavoir libérée:    #include <stdio.h>    #include "color_list.h...
Les listes●   normal: la condition darrêt de    print_list est list==NOTHING, or on a    mis la valeur EMPTY_CELL●   solut...
Les listes●   la fausse bonne idée: faire en sorte que    free_list modifie son paramètre:      /**        * Frees the who...
Les listes●   pourquoi nest-ce pas une bonne idée ?●   parce quune même cellule peut être    référencée plusieurs fois, et...
Upcoming SlideShare
Loading in...5
×

C5 types structures

215

Published on

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
215
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
9
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

C5 types structures

  1. 1. Cours de C Types structurés Sébastien Paumierpaumier@univ-mlv.fr Illustrations provenant du site http://tux.crystalxp.net/ 1
  2. 2. Les structures● objets regroupant plusieurs données appelées "champs"● à définir hors dune fonction● définition: struct nom { type_champ1 nom_champ1; type_champ2 nom_champ2; ... };paumier@univ-mlv.fr 2
  3. 3. Les structures● déclaration dune variable: struct nom_type nom_var;● accès aux champs: nom_var.nom_champ struct complex { double real; double imaginary; }; int main(int argc,char* argv[]) { struct complex c; c.real=1.2; c.imaginary=6.3; printf("%f+%f*in",c.real,c.imaginary); return 0; }paumier@univ-mlv.fr 3
  4. 4. Choix des champs● on peut mettre tout ce dont le compilateur connaît la taille● on ne peut donc pas mettre la structure elle-même: struct list { int value; struct list next; };$>gcc -Wall -ansi struct.cstruct.c:7: champ « next » a un type incompletpaumier@univ-mlv.fr 4
  5. 5. Structures récursives● mais on peut mettre un pointeur sur la structure, car la taille des pointeurs est connue: struct list { int value; struct list* next; };paumier@univ-mlv.fr 5
  6. 6. Imbrication de structures● un champ peut être une structure: struct id { char firstname[MAX]; char lastname[MAX]; }; struct people { pas dambiguïté car le struct id id; type ne sappelle pas int age; }; id mais struct id int main(int argc,char* argv[]) { struct people p; strcpy(p.id.firstname,"Master"); strcpy(p.id.lastname,"Yoda"); p.age=943; /* ... */ return 0; }paumier@univ-mlv.fr 6
  7. 7. Imbrication de structures● 2 structures peuvent sappeler lune lautre, à condition dutiliser des pointeurs: struct state { struct transition* t; char final; }; struct transition { char letter; struct state* dest; struct transition* next; };paumier@univ-mlv.fr 7
  8. 8. Contraintes sur les structures● champs organisés dans lordre de leur déclarations: struct foo { int a; char b; float c; }; int main(int argc,char* argv[]) { struct foo f; printf("%p < %p < %pn", &(f.a),&(f.b),&(f.c)); return 0; }$>./a.out0022FF58 < 0022FF5C < 0022FF60paumier@univ-mlv.fr 8
  9. 9. Alignement● adresse dune structure = adresse de son premier champ● pour les autres champs, le compilateur fait de lalignement pour avoir, selon limplémentation: – des adresses multiples de la taille des données – des adresses multiples de la taille des pointeurs – ...paumier@univ-mlv.fr 9
  10. 10. Alignement● taille variable suivant lordre des champs: struct to { struct ta { char a; int a; int b; char b; sizeof(ta)=8 char c; sizeof(to)=12 char c; char d; char d; }; };● ne jamais essayer de deviner ladresse dun champ ou la taille dune structure: – noms des champs – sizeofpaumier@univ-mlv.fr 10
  11. 11. Alignementstruct to { struct ta { char a; int a; int b; char b; sizeof(ta)=8 char c; sizeof(to)=12 char c; char d; char d;}; }; @+0 a @+0 a @+4 @+4 b @+5 c b @+6 d @+8 c @+9 dpaumier@univ-mlv.fr 11
  12. 12. Initialisation ● struct to t={val0,val1,...,valn-1}; struct to t={a,145,y,u}; ● seulement lors de la déclaration int main(int argc,char* argv[]) { struct to t; t={a,145,y,u}; printf("%c %d %c %cn",t.a,t.b,t.c,t.d); return 0; }$>gcc -Wall -ansi struct.cstruct.c: Dans la fonction « main »:struct.c:33: erreur danalyse syntaxique avant le jeton « { » paumier@univ-mlv.fr 12
  13. 13. Opérations● laffectation fonctionne int main(int argc,char* argv[]) { struct to z={a,145,y,u}; struct to t=z; printf("%c %d %c %cn",t.a,t.b,t.c,t.d); return 0; }● attention: si un champ est un pointeur, on ne copie que ladresse● pas dopérateur de comparaison ⇨ à écrire soi-mêmepaumier@univ-mlv.fr 13
  14. 14. Structures en paramètres● les structures sont passées par valeur! – non modifiables – peuvent occuper beaucoup de place sur la pile (tableaux) – temps de recopie● toujours les passer par adressepaumier@univ-mlv.fr 14
  15. 15. Structures en paramètres struct array { struct array { int t[100000]; int t[100000]; int size; int size; }; }; void f(struct array a) { void f(struct array* a) { int i; int i; for (i=0;i<a.size;i++) { for (i=0;i<(*a).size;i++) { printf("%dn",a.t[i]); printf("%dn",(*a).t[i]); } } } } attention au parenthésage: (*a).t[i] ≠ *a.t[i]paumier@univ-mlv.fr 15
  16. 16. Structures en paramètres● passage dadresse = – gain de temps – gain despace sur la pile – on peut modifier la structure● notation simplifiée: (*a).size = a->size void f(struct array* a) { void f(struct array* a) { int i; int i; for (i=0;i<(*a).size;i++) { for (i=0;i<a->size;i++) { printf("%dn",(*a).t[i]); printf("%dn",a->t[i]); } } } }paumier@univ-mlv.fr 16
  17. 17. Retourner une structure● on peut, mais cest une opération de copie sur la pile● mêmes problèmes que pour le passage par valeur● à nutiliser que très soigneusement● le plus souvent, il faudra utiliser de lallocation dynamiquepaumier@univ-mlv.fr 17
  18. 18. Les unionsunion toto { zone mémoire que lon type1 nom1; peut voir soit comme un type2 nom2; type1, soit comme un ... type2, etc. typeN nomN;};● sutilisent comme les union toto { char a; float b; structures }; void foo(union toto* t) { t->a=z; }paumier@univ-mlv.fr 18
  19. 19. Les unions● taille = taille du plus grand champ● au programmeur de savoir quel champ doit être utilisé union toto { char a; char s[16]; }; $>./a.out int main(int argc,char* argv[]) { $oucou union toto t; strcpy(t.s,"coucou"); t.a=$; printf("%sn",t.s); return 0; }paumier@univ-mlv.fr 19
  20. 20. Les unions● utiles quand on doit manipuler des informations exclusives les unes des autres union student { char login[16] int id; };● peuvent être utilisées anonymement dans une structure struct student { char name[256]; union { char login[16]; int id; }; };paumier@univ-mlv.fr 20
  21. 21. Unions complexes● on peut mettre des structures (anonymes) dans les unions union color { /* RGB representation */ struct { unsigned char red,blue,green; }; /* 2 colors: 0=black 1=white */ char BandW; }; on peut utiliser soit red, blue et green, soit BandWpaumier@univ-mlv.fr 21
  22. 22. Quel(s) champ(s) utiliser ?● encapsulation dans une structure avec un champ dinformation struct color { /* 0=RGB 1=black & white */ char type; union { /* RGB representation */ struct { unsigned char red,blue,green; }; /* 2 colors: 0=black 1=white */ char BandW; }; };paumier@univ-mlv.fr 22
  23. 23. Les énumérations● enum nom {id0,id1,...,idn-1};● si on a une variable de type enum nom, elle pourra prendre les valeurs idi enum gender {male,female}; void init(enum gender *g,char c) { *g=(c==m)?male:female; }paumier@univ-mlv.fr 23
  24. 24. Les énumérations● valeurs de type int● par défaut, commencent à 0 et vont de 1 en 1● on peut les modifier enum color { blue=45, green, /* 46 */ red, /* 47 */ yellow=87, black /* 88 */ };paumier@univ-mlv.fr 24
  25. 25. Les énumérations● on peut avoir plusieurs fois la même valeur enum color { blue=45, BLUE=blue, Blue=blue, green/* =46 */, GREEN=green, Green=green }; int main(int argc,char* argv[]) { printf("%d %d %d %d %d %dn", blue,BLUE,Blue,green,GREEN,Green); return 0; } $>./a.out 45 45 45 46 46 46paumier@univ-mlv.fr 25
  26. 26. Contrôles des valeurs● contrairement aux espoirs du programmeur, pas de contrôle! enum gender {male=m,female=f}; enum color {blue,red,green}; int main(int argc,char* argv[]) { enum gender g=z; enum color c=g; /* ... */ return 0; }paumier@univ-mlv.fr 26
  27. 27. Contrôles des valeurs ● seul contrôle: avec -Wall, gcc indique sil manque des cas dans un switch (quand il ny a pas de default) enum color {blue,red,green,yellow}; void foo(enum color c) { switch (c) { case blue: /* ... */ break; case red: /* ... */ break; }$>gcc -Wall -ansi enum.c }enum.c: Dans la fonction « foo »:enum.c:24: AVERTISSEMENT: valeur dénumération « green » nest pastraitée dans le switchenum.c:24: AVERTISSEMENT: valeur dénumération « yellow » nest pastraitée dans le switch paumier@univ-mlv.fr 27
  28. 28. Déclaration de constantes● si on veut juste déclarer des constantes, on peut utiliser une énumération anonyme enum {Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday}; char* names[]={"Monday","Tuesday","Wednesday","Thursday","Friday", "Saturday","Sunday"}; void print_day(int day) { printf("%sn",names[day]); } int main(int argc,char* argv[]) { print_day(Saturday); return 0; }paumier@univ-mlv.fr 28
  29. 29. Combinaison union/enum● quand on utilise une union, cest plus propre de décrire les alternatives avec une énumération: enum cell_type {EMPTY,BONUS,MALUS,PLAYER,MONSTER}; struct cell { enum cell_type type; union { Bonus bonus; Malus malus; Player player; Monster monster; }; };paumier@univ-mlv.fr 29
  30. 30. typedef● typedef type nom;● permet de donner un nom à un type, simple ou composé● pratique pour éviter de recopier les mots-clés struct, union et enum typedef signed char sbyte; typedef unsigned char ubyte; typedef struct cell Cell; typedef enum color Color;paumier@univ-mlv.fr 30
  31. 31. typedef● pas de nouveaux types● seulement des synonymes interchangeables struct array { int t[N]; int size; }; typedef struct array Array; int main(int argc,char* argv[]) { Array a; struct array b=a; /* ... */ return 0; }paumier@univ-mlv.fr 31
  32. 32. typedef● pour les types structurés, deux modes de définition:enum cell_type {EMPTY,BONUS,MALUS, typedef enum {EMPTY,BONUS,MALUS, PLAYER,MONSTER}; PLAYER,MONSTER} CellType;typedef enum cell_type CellType; typedef struct { CellType type;struct cell { union { CellType type; Bonus bonus; union { Malus malus; Bonus bonus; Player player; Malus malus; Monster monster; Player player; }; Monster monster; } Cell; };};typedef struct cell Cell;paumier@univ-mlv.fr 32
  33. 33. Les listes● application: coder une liste chaînée de noms de couleurs● utilisons une structure pour représenter une cellule de la liste: #define COLOR_NAME_MAX 128 typedef struct { char name[COLOR_NAME_MAX]; int next; } ColorList;paumier@univ-mlv.fr 33
  34. 34. Les listes● la mémoire est simulée par un tableau de telles structures: /* The cell array that represents memory */ #define SIZE 1000 extern ColorList memory[SIZE];● une cellule est caractérisée par son indice dans ce tableau● il faut une convention pour désigner labsence de cellule en fin de liste: /* The equivalent of NULL */ #define NOTHING -1paumier@univ-mlv.fr 34
  35. 35. Les listes● pour gérer la mémoire, il faut savoir quelles cellules sont disponibles● astuce: utilisons une valeur spéciale pour le champ next /* A convention to indicate when a cell is not used */ #define EMPTY_CELL -2paumier@univ-mlv.fr 35
  36. 36. Les listes● il faut savoir allouer et désallouer: /** * Returns the index of the first free cell, or NOTHING if there * is none. */ int get_free_cell() { int i; for (i=0;i<SIZE;i++) { if (memory[i].next==EMPTY_CELL) return i; } return NOTHING; } /** * Marks the given memory cell as being free. */ void free_cell(int index) { memory[index].next=EMPTY_CELL; }paumier@univ-mlv.fr 36
  37. 37. Les listes● on peut maintenant ajouter une couleur en tête de liste:/** * Adds a cell representing the given color at the beginning of the given * list. Returns 1 in case of success, 0 if there is no more memory. */int add_color(int *list,char* color) { int index=get_free_cell(); if (index==NOTHING) { return 0; } strcpy(memory[index].name,color); memory[index].next=(*list); (*list)=index; return 1;}paumier@univ-mlv.fr 37
  38. 38. Les listes● on veut pouvoir afficher la liste: /** * Prints the given list. */ void print_list(int list) { printf("list="); while (list!=NOTHING) { printf("%s ",memory[list].name); list=memory[list].next; } printf("n"); }paumier@univ-mlv.fr 38
  39. 39. Les listes● enfin, il faut pouvoir libérer une liste entière: /** * Frees the whole given list. */ void free_list(int list) { int tmp; while (list!=NOTHING) { tmp=memory[list].next; free_cell(list); list=tmp; } }paumier@univ-mlv.fr 39
  40. 40. Les listes● on peut maintenant tester notre bibliothèque: #include <stdio.h> #include "color_list.h" int main(int argc,char* argv[]) { init_memory(); int list=NOTHING; add_color(&list,"blue"); $>./a.out add_color(&list,"black"); add_color(&list,"red"); list=red black blue print_list(list); free_list(list); return 0; }paumier@univ-mlv.fr 40
  41. 41. Les listes● bug si on essaie dafficher la liste après lavoir libérée: #include <stdio.h> #include "color_list.h" $>./a.out int main(int argc,char* argv[]) { list=red black blue init_memory(); int list=NOTHING; list=blue blue blue add_color(&list,"blue"); add_color(&list,"black"); blue blue blue blue add_color(&list,"red"); blue blue blue blue print_list(list); free_list(list); blue blue blue print_list(list); blue... return 0; }paumier@univ-mlv.fr 41
  42. 42. Les listes● normal: la condition darrêt de print_list est list==NOTHING, or on a mis la valeur EMPTY_CELL● solution: mettre list à NOTHING après lappel à free_list int main(int argc,char* argv[]) { ... free_list(list); list=NOTHING; print_list(list); return 0; }paumier@univ-mlv.fr 42
  43. 43. Les listes● la fausse bonne idée: faire en sorte que free_list modifie son paramètre: /** * Frees the whole given list and sets *list to NOTHING. */ void free_list2(int *list) { int tmp; while (*list!=NOTHING) { tmp=memory[*list].next; free_cell(*list); *list=tmp; } }paumier@univ-mlv.fr 43
  44. 44. Les listes● pourquoi nest-ce pas une bonne idée ?● parce quune même cellule peut être référencée plusieurs fois, et quon ne va mettre à jour quune seule référence:int main(int argc,char* argv[]) { $>./a.out ... list=red black blue print_list(list); int list2=list; list= free_list2(&list); list=blue blue blue print_list(list); print_list(list2); blue blue blue blue return 0; blue blue blue blue} blue...paumier@univ-mlv.fr 44
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×