diff --git a/exemples/opaque/Makefile b/exemples/opaque/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..398598b57c292f45e62c84d40acb926f323ec6f2 --- /dev/null +++ b/exemples/opaque/Makefile @@ -0,0 +1,13 @@ +CC:=gcc +CFLAGS:=-Wall -Wextra -pedantic -g -fsanitize=address -fsanitize=leak -std=c2x +LDFLAGS:=-fsanitize=address -fsanitize=leak + +main: opaque.o main.o + $(CC) -o $@ $^ $(LDFLAGS) + +opaque.o: opaque.h + +.PHONY: clean + +clean: + rm -f *.o main \ No newline at end of file diff --git a/exemples/opaque/main.c b/exemples/opaque/main.c new file mode 100644 index 0000000000000000000000000000000000000000..14f4b6632704dcbd859ee7311d040045e24dcff8 --- /dev/null +++ b/exemples/opaque/main.c @@ -0,0 +1,11 @@ +#include "opaque.h" +#include <stdio.h> + +int main() +{ + table t; + init(&t); + set(t, 10); + printf("%d\n", get(t)); + destroy(&t); +} \ No newline at end of file diff --git a/exemples/opaque/opaque.c b/exemples/opaque/opaque.c new file mode 100644 index 0000000000000000000000000000000000000000..2c6f09a550c23dcf1cf9f46ec16523623a34514d --- /dev/null +++ b/exemples/opaque/opaque.c @@ -0,0 +1,29 @@ +#include "opaque.h" +#include <stdlib.h> + +struct _table +{ + int len; + int *data; +}; + +void init(table *tab) +{ + *tab = malloc(sizeof(struct _table)); +} + +void destroy(table *tab) +{ + free(*tab); + *tab = NULL; +} + +int get(table tab) +{ + return tab->len; +} + +void set(table tab, int len) +{ + tab->len = len; +} diff --git a/exemples/opaque/opaque.h b/exemples/opaque/opaque.h new file mode 100644 index 0000000000000000000000000000000000000000..9c878701313c94ab9acd830f1eed4713f40a59e0 --- /dev/null +++ b/exemples/opaque/opaque.h @@ -0,0 +1,13 @@ +#ifndef OPAQUE_H +#define OPAQUE_H + +struct _table; + +typedef struct _table *table; + +void init(table *tab); +void set(table tab, int len); +int get(table tab); +void destroy(table *tab); + +#endif diff --git a/slides/opaque.md b/slides/opaque.md new file mode 100644 index 0000000000000000000000000000000000000000..d14b1a8beb0befadc42de36cee42627d4206628f --- /dev/null +++ b/slides/opaque.md @@ -0,0 +1,153 @@ +--- +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() { + struct table *t = create(); + 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 l'exemple de la hashmap on `get/set` les variables des structs! + +## Yaka + +* Utiliser les types opaques pour la hashmap! +