diff --git a/slides/genericite.md b/slides/genericite.md
new file mode 100644
index 0000000000000000000000000000000000000000..448f3cb47be67de05abbf01941e032603ef2603a
--- /dev/null
+++ b/slides/genericite.md
@@ -0,0 +1,180 @@
+---
+title: "La généricité"
+date: "2024-03-25"
+---
+
+# Problématique
+
+* En C on doit écrire chaque algorithme/structures de données pour des types
+  précis (`int`, `double`, `char`, ...).
+
+    ```
+    void int_sort(int size, int tab[size]);    // tri d'entiers
+    void double_sort(int size, int tab[size]); // tri de double
+    void char_sort(int size, char tab[size]);  // tri de char
+    ```
+* Duplication du code pour chaque type possible et imaginable.
+* On aimerait un moyen pour pouvoir représenter "n'importe quel type" sans
+  réécrire tout le code.
+
+# La généricité
+
+## Une "solution": `void *`{.C}
+
+* En général, un pointeur connaît son **adresse** et le **type** des données sur lesquelles il pointe.
+ 
+    ```C
+    int *a = malloc(sizeof(*a));
+    int *b = malloc(sizeof(int));
+    ```
+* Un `void *`{.C} le connaît **que** son adresse, au programmeur de pas faire n'importe quoi.
+* Vous avez déjà utilisé des fonctions utilisant des `void *`{.C}
+ 
+    ```C
+    void *malloc(size_t size);
+    void free(void *);
+    ```
+
+# Attention danger
+
+* Ne permet pas au compilateur de vérifier les types.
+* Les données pointées n'ayant pas de type, il faut déréférencer avec précaution:
+  
+    ```C
+    int a = 2;
+    void *b = &a; //jusqu'ici tout va bien
+    double c = *b; // argl!
+    ```
+* Une attention accrue est nécessaire.
+
+# Cas particuier: on sait pas comment libérer la mémoire
+
+## Exemple
+
+```C 
+struct tab {
+    int *t;
+}
+struct tab *tmp = malloc(sizeof(*tmp));
+tmp->t = malloc(10 * sizeof(*(tmp->t)));
+free(tmp); // memory leak of tmp->t...
+```
+
+. . .
+
+## Solution: tout faire à la main
+
+```C 
+free(tmp->t);
+free(tmp);
+```
+
+# Exemple simple
+
+* On souhaite échanger deux pointeurs
+
+    ```C 
+    int *a = malloc();
+    int *b = malloc();
+    swap(&a, &b);
+    ```
+* Comment écrire `swap()` pour que le code ci-dessus marche pour n'importe quel
+  type?
+
+. . .
+
+```C 
+void swap(void **a, void **b) {
+    void *tmp = *a;
+    *a = *b;
+    *b = tmp;
+}
+```
+
+
+
+# Cas d'utilisation (1/4)
+
+\footnotesize
+
+* La somme d'un tableau de type arbitraire (facile non?)
+
+    ```C
+    void sum(void *tab, int length, size_t size_elem, void *zero,
+        void (*add)(void *, void *)) {
+        for (int i = 0; i < length; ++i) {
+            void *rhs = (void *)((char *)tab + i * size_elem);
+            add(zero, rhs);
+        } // de combien on "saute" avec un void *?
+    }
+    ```
+* Pour des entiers
+
+    ```C 
+    void int_add(void *lhs, void *rhs) {
+        *((int *)lhs) += *((int *)rhs); // cast d'entiers
+    }
+    int zero  = 0;
+    int tab[] = {1, -2, 4, 5};
+    sum(tab, 4, sizeof(int), &zero, int_add);
+    printf("%d\n", zero);
+    ```
+
+# Cas d'utilisation (2/4)
+
+## Que fait cette fonction?
+
+\footnotesize
+
+```C
+void *foo(void *tab, int n_items, int s_items, 
+          bool (*bar)(void *, void *)) {
+    if (n_items <= 0 || s_items <= 0 || NULL == tab) {
+        return NULL;
+    }
+    void *elem = tab;
+    for (int i = 1; i < n_items; ++i) {
+        // void pointer arithmetics is illegal in C 
+        // (gcc is ok though)
+        void *tmp_elem = (void *)((char *)tab + i*s_items);
+
+        if (bar(elem, tmp_elem)) {
+            elem = tmp_elem;
+        }
+    }
+    return elem;
+}
+```
+
+# Cas d'utilisation (3/4)
+
+## Avec un tableau de `int`{.C}
+
+```C
+bool cmp_int(void *a, void *b) {
+    return (*(int *)a < *(int *)b);
+}
+
+int main() {
+    int tab[] = {-1, 2, 10, 3, 8};
+    int *a = foo(tab, 5, sizeof(int), cmp_int);
+    printf("a = %d\n", *a);
+}
+```
+
+# Cas d'utilisation (4/4)
+
+## Avec un tableau de `double`{.C}
+
+```C
+bool cmp_dbl(void *a, void *b) {
+    return (*(double *)a < *(double *)b);
+}
+
+int main() {
+    double tab[] = {-1.2, 2.1, 10.5, 3.6, 18.1};
+    double *a = foo(tab, 5, sizeof(double), cmp_dbl);
+    printf("a = %f\n", *a);
+}
+```
+
diff --git a/slides/pointeurs_avances.md b/slides/pointeurs_avances.md
new file mode 100644
index 0000000000000000000000000000000000000000..3cfd92a6a506bf22523e78f92ff0ef4a60275093
--- /dev/null
+++ b/slides/pointeurs_avances.md
@@ -0,0 +1,92 @@
+---
+title: "Pointeurs avancés"
+date: "2024-03-24"
+---
+
+# Pointeurs et `const`
+
+\footnotesize
+
+- Le mot-clé `const` permet de déclarer des valeurs **constantes** qui ne changeront plus en cours d'exécution du programme.
+
+    ```C
+    const int a = 1;
+    a = 2; // interdit, erreur de compilation!
+    ```
+
+## Deux niveaux de constance
+
+- Mais qu'est-ce que cela veut dire pour les pointeurs?
+* Constance de la valeur de l'adresse? de la valeur pointée? des deux?
+
+    ```C
+    int n = 12;
+    const int *p = &n; // la valeur *p est const, p non
+    int const *p = &n; // la valeur *p est const, p non
+    int *const p = &n; // la valeur p est const, *p non
+    const int *const p = &n; // la valeur p et *p sont const
+    ```
+
+# Pointeurs et `const`
+
+## Exemples
+
+```C
+int n = 12; int m = 13;
+const int *p = &n; // la valeur *p est const, p non
+*p = m; // erreur de compilation.
+p = &m; // OK
+int const *p = &n; // la valeur *p est const, p non
+*p = m; // erreur de compilation.
+p = &m; // OK
+int *const p = &n; // la valeur p est const, *p non
+*p = m; // OK
+p = &m; // erreur de compilation.
+const int *const p = &n; // la valeur p et *p sont const
+*p = m; // erreur de compilation.
+p = &m; // erreur de compilation.
+```
+
+# Rappel: pointeurs et fonction
+
+## Faites un dessin de ce qui se passe en mémoire
+
+```C
+void foo(int *a) {
+    *a = 3;
+}
+void bar(int a) {
+    a = 12;
+}
+int main() {
+    int a = 1;
+    foo(&a); // Que vaut a?
+    bar(a);  // Que vaut a?
+}
+```
+
+# Pointeurs et `const`
+
+## Fonctions
+
+```C
+void foo(int *a);
+void foo(const int *a); // on pourra pas changer *a
+void foo(int *const a); // inutile on peut pas changer a
+void foo(const int *const a); // identique à ci-dessus
+```
+
+## Mais.....
+
+```C
+const int a = 0;
+int *b = (int *)&a;
+*b = 7;
+printf("a = %d\n", a); // affiche quoi?
+```
+
+# Utilité
+
+* Permet d'empêcher une mauvaise utilisation des arguments,
+* Permet de documenter le code: on sait que la variable ne sera pas modifiée.
+