diff --git a/slides/cours_3.md b/slides/cours_3.md
index 5d22f586c4177e012ba0d793eb50244d837368ae..430521582daacf86360559737b1524c6b3b91b0e 100644
--- a/slides/cours_3.md
+++ b/slides/cours_3.md
@@ -338,8 +338,6 @@ Algorithme de génération de nombres premiers.
 
 \footnotesize
 
-## Une solution possible
-
 ```C
 #include <stdio.h>
 #include <stdbool.h>
@@ -353,11 +351,8 @@ int main() {
       if (tab[i]) {
          printf("%d ", i);
          int j = i;
-         while (true) {
+         while (j < SIZE) {
             j += i;
-            if (j >= SIZE) {
-               break;
-            }
             tab[j] = false;
          } 
       } 
@@ -486,10 +481,11 @@ for (int i = 0; i < NX; ++i) {
 
 ## Nombres à virgule flottante, simple/double précision
 
-# Structures (1/N)
+# Types complexes: `struct`{.C} (1/6)
 
 ## Fractions
 
+* Plusieurs variables qu'on aimerait regrouper dans un seul type: `struct`{.C}.
 * Numérateur: `int num`;
 * Dénominateur: `int denom`.
 
@@ -504,16 +500,98 @@ int denom3 = denom1 * denom2;
 
 ## Pas super pratique....
 
-# Structures (2/N)
+# Types complexes: `struct`{.C} (2/6)
 
 ## On peut faire mieux
 
 ```C
-struct fraction {
+struct fraction { // déclaration du type
     int32_t num, denom;
 }
+
+struct fraction frac; // déclaration de frac
 ```
 
+# Types complexes: `struct`{.C} (3/6)
+
+## Simplifications
+
+- `typedef`{.C} permet de définir un nouveau type.
+
+    ```C
+    typedef unsinged int uint;
+    typedef struct fraction fraction_t;
+    typedef struct fraction {
+        int32_t num, denom;
+    } fraction_t;
+    ```
+- L'initialisation peut aussi se faire avec
+
+    ```C
+    fraction_t frac = {1, -2}; // num = 1, denom = -2
+    fraction_t frac = {.denom = 1, .num = -2};
+    fraction_t frac = {.denom = 1}; // argl! .num non initialisé 
+    fraction_t frac2 = frac; // copie
+    ```
+
+# Types complexes: `struct`{.C} (4/6)
+
+## Pointeurs
+
+- Comme pour tout type, on peut avoir des pointeurs vers un `struct`{.C}.
+- Les champs sont accessible avec le sélecteur `->`{.C}
+
+    ```C
+    fraction_t *frac; // on crée un pointeur
+    frac->num = 1;    // seg fault...
+    frac->denom = -1; // mémoire pas allouée.
+    ```
+
+![La représentation mémoire de `fraction_t`.](figs/pointer_struct.svg){width=100%}
+
+# Types complexes: `struct`{.C} (5/6)
+
+## Initialisation
+
+- Avec le passage par **référence** on peut modifier un struct *en place*.
+- Les champs sont accessible avec le sélecteur `->`{.C}
+
+    ```C
+    void fraction_init(fraction_t *frac, 
+                      int32_t re, int32_t im) 
+    {
+        // frac a déjà été allouée
+        frac->num   = frac;
+        frac->denom = denom;
+    }
+    int main() {
+        fraction_t frac; // on alloue une fraction
+        fraction_init(&frac, 2, -1); // on l'initialise
+    }
+    ```
+
+# Types complexes: `struct`{.C} (6/6)
+
+## Initialisation version copie
+
+* On peut allouer une fraction, l'initialiser et le retourner.
+* La valeur retournée peut être copiée dans une nouvelle structure.
+
+    ```C
+    fraction_t fraction_create(int32_t re, int32_t im) {
+        fraction_t frac;
+        frac.num = re;
+        frac.denom = im;
+        return frac;
+    }
+    int main() {
+        // on crée une fraction et on l'initialise
+        // en copiant la fraction créé par fraction_create
+        // deux allocation et une copie
+        fraction_t frac = fraction_create(2, -1); 
+    }
+    ```
+
 # TODO jusqu'aux vacances
 
 * Refactorisation