--- title: "Types opaques" date: "2023-03-07" --- # Types composés * Jusqu'ici les `struct` sont dans les `.h` et sont *transparents* ```C // table.h typedef struct _table { int *data; int length; } table; // main.c table tab; // membres de tab accessibles directement tab.length = 10; tab.data = malloc(tab.length * sizeof(int)); tab.data[9] = 10; ``` # Types opaques * Afin de cacher les détails de l'implémentation. * Afin d'éviter les modifications directs des données. * Afin de protéger le monde de la dévastation! * Définition de types **opaques**: * Variables dans les structures ne sont pas accessibles. * Variables dans les structures ne sont pas modifiables. * Les variables ne sont même pas connues. * Nécessité de passer par des fonctions pour initialiser/modifier les instances de types opaques. * Très souvent utilisés pour les structures de données abstraites (table de hachage, pile, file, ...). # Utilisation d'un type opaque: problème? * Dans `opaque.h` ```C struct table; ``` * Dans `opaque.c` ```C struct table { int a; } ``` * Dans `main.c` ```C int main() { struct table t; } // error: storage size of ‘t’ isn’t known ``` * La taille de `table` n'est pas connue à la compilation! * Comment faire? # Utilisation d'un type opaque: pointeur! \footnotesize * Dans `opaque.h` ```C struct table; struct table *create(); void init(struct table **t); ``` * Dans `opaque.c` ```C struct table { int a; } struct table *create() { struct table *t = malloc(sizeof(*t)); return t; } void init(struct table **t) { *t = malloc(sizeof(**t)); } ``` * Dans `main.c` ```C int main() { struct table *t = create(); init(&t); t->a = 2; // Interdit, set(2) printf("%d\n", t->a); // Interdit, get() } ``` # Un peu plus joli: typedef! (1/2) * Dans `opaque.h` ```C struct _table; typedef struct _table * table; void init(table *t); void set_a(table t, int a); int get_a(table t); ``` * Dans `opaque.c` ```C struct _table { int a; } void init(table *t) { *t = malloc(sizeof(**t)); (*t)->a = 0; } void set_a(table t, int a) { t->a = a; } int get_a(table t) { return t->a; } ``` # Un peu plus joli: typedef! (2/2) * Dans `main.c` ```C int main() { table t; init(&t); set_a(t, 10); printf("%d\n", get_a(t)); } ``` * On a fait les fonctions `get_a()` et `set_a()` comme exemples, mais... . . . * c'est pas forcément nécessaire d'implémenter (`get/set`). . . . * Par exemple, pour la hashmap on `get/set` les variables des structs! ## Yaka * Utiliser les types opaques pour la hashmap!