From 67f0541bac88417824010ab88248491c63e564d8 Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Mon, 6 Mar 2023 22:04:19 +0100 Subject: [PATCH] added opaque --- exemples/opaque/Makefile | 13 ++++ exemples/opaque/main.c | 11 +++ exemples/opaque/opaque.c | 29 ++++++++ exemples/opaque/opaque.h | 13 ++++ slides/opaque.md | 153 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+) create mode 100644 exemples/opaque/Makefile create mode 100644 exemples/opaque/main.c create mode 100644 exemples/opaque/opaque.c create mode 100644 exemples/opaque/opaque.h create mode 100644 slides/opaque.md diff --git a/exemples/opaque/Makefile b/exemples/opaque/Makefile new file mode 100644 index 0000000..398598b --- /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 0000000..14f4b66 --- /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 0000000..2c6f09a --- /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 0000000..9c87870 --- /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 0000000..d14b1a8 --- /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! + -- GitLab