diff --git a/Theorie/C/datatypes.rst b/Theorie/C/datatypes.rst
index 6927710c6fc0c24046bc7d9fc731a34c781bf924..299b4a89c1198eccdee08e1121319dfde167d3d2 100644
--- a/Theorie/C/datatypes.rst
+++ b/Theorie/C/datatypes.rst
@@ -85,7 +85,7 @@ convention préfixé par ``0x`` tandis qu'un nombre entier en notation
 binaire est préfixé par ``0b``. Ainsi, les déclarations ci-dessous
 correspondent toutes à la même valeur.
 
-.. literalinclude:: /_static/src/C/S2-src/num.c
+.. literalinclude:: /C/S2-src/num.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -109,7 +109,7 @@ contrairement à la notation hexadécimale qui fait partie du langage.
  ``65 et 53 sont différents`` car le compilateur C interprète la ligne
  ``j=065;`` comme contenant un entier en notation octale et non décimale.
 
- .. literalinclude:: /_static/src/C/S2-src/octal.c
+ .. literalinclude:: /C/S2-src/octal.c
     :encoding: utf-8
     :language: c
     :start-after: ///AAA
@@ -240,7 +240,7 @@ peut causer des erreurs dans certains calculs. Par exemple,
 voici un petit programme qui affiche les 10 premières puissances de
 cinq et dix.
 
-.. literalinclude:: /_static/src/C/S2-src/short.c
+.. literalinclude:: /C/S2-src/short.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -248,7 +248,7 @@ cinq et dix.
 
 Lorsqu'il est exécuté, ce programme affiche la sortie suivante.
 
-.. literalinclude:: /_static/src/C/S2-src/short.out
+.. literalinclude:: /C/S2-src/short.out
    :encoding: utf-8
    :language: console
 
@@ -281,7 +281,7 @@ est décomposée en trois parties [#fexemple]_ :
  - `e` bits sont réservés pour stocker l'exposant [#fexposant]_.
  - Les `f` bits de poids faible servent à stocker la partie fractionnaire du nombre réel.
 
-.. figure:: /_static/figures/C/svg/Float_example.png
+.. figure:: /C/svg/Float_example.png
    :align: center
    :scale: 100
 
@@ -316,7 +316,7 @@ Les tableaux
 
 En langage C, les tableaux permettent d'agréger des données d'un même type. Il est possible de définir des vecteurs et des matrices en utilisant la syntaxe ci-dessous.
 
-.. literalinclude:: /_static/src/C/S2-src/array.c
+.. literalinclude:: /C/S2-src/array.c
    :language: c
    :encoding: utf-8
    :start-after: ///AAA
@@ -326,7 +326,7 @@ Les premières versions du langage C ne permettaient que la définition de table
 
 Un tableau à une dimension peut s'utiliser avec une syntaxe similaire à celle utilisée par Java. Dans un tableau contenant ``n`` éléments, le premier se trouve à l'indice ``0`` et le dernier à l'indice ``n-1``. L'exemple ci-dessous présente le calcul de la somme des éléments d'un vecteur.
 
-.. literalinclude:: /_static/src/C/S2-src/array.c
+.. literalinclude:: /C/S2-src/array.c
    :language: c
    :encoding: utf-8
    :start-after: ///CCC
@@ -334,7 +334,7 @@ Un tableau à une dimension peut s'utiliser avec une syntaxe similaire à celle
 
 Le langage C permet aussi la manipulation de matrices carrées ou rectangulaires qui sont composées d'éléments d'un même type. L'exemple ci-dessous calcule l'élément minimum d'une matrice rectangulaire. Il utilise la constante ``FLT_MAX`` qui correspond au plus grand nombre réel représentable avec un ``float`` et qui est définie dans `float.h`_.
 
-.. literalinclude:: /_static/src/C/S2-src/array.c
+.. literalinclude:: /C/S2-src/array.c
    :language: c
    :encoding: utf-8
    :start-after: ///EEE
@@ -374,7 +374,7 @@ caractères. À titre d'exemple, une fonction `toupper(3)`_ permettant
 de transformer un caractère représentant une minuscule dans le
 caractère représentant la majuscule correspondante peut s'écrire :
 
-.. literalinclude:: /_static/src/C/S2-src/toupper.c
+.. literalinclude:: /C/S2-src/toupper.c
    :language: c
    :encoding: utf-8
    :start-after: ///AAA
@@ -441,7 +441,7 @@ fonctions de manipulation de chaînes de
 caractères. À titre d'exemple, la fonction ci-dessous calcule
 la longueur d'une chaîne de caractères.
 
-.. literalinclude:: /_static/src/C/S2-src/strlen.c
+.. literalinclude:: /C/S2-src/strlen.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -556,7 +556,7 @@ donnée. Les adresses de données en mémoire sont rarement affichées,
 mais quand c'est le cas, on utilise la notation hexadécimale comme
 dans l'exemple ci-dessous.
 
-.. literalinclude:: /_static/src/C/S2-src/ptr.c
+.. literalinclude:: /C/S2-src/ptr.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -564,7 +564,7 @@ dans l'exemple ci-dessous.
 
 L'exécution de ce fragment de programme produit la sortie suivante.
 
-.. literalinclude:: /_static/src/C/S2-src/ptr.out
+.. literalinclude:: /C/S2-src/ptr.out
    :encoding: utf-8
    :language: console
 
@@ -591,7 +591,7 @@ l'expression ``*ptr``. Il est
 représenté dans l'exemple ci-dessous.
 
 
-.. literalinclude:: /_static/src/C/S2-src/ptrex.c
+.. literalinclude:: /C/S2-src/ptrex.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -599,7 +599,7 @@ représenté dans l'exemple ci-dessous.
 
 L'exécution de ce fragment de programme produit la sortie suivante.
 
-.. literalinclude:: /_static/src/C/S2-src/ptrex.out
+.. literalinclude:: /C/S2-src/ptrex.out
    :encoding: utf-8
    :language: console
 
@@ -609,7 +609,7 @@ En pratique en C, les notations ``char*`` et ``char[]`` sont
 les pointeurs, la fonction de calcul de la longueur d'une chaîne de
 caractères peut se réécrire comme suit.
 
-.. literalinclude:: /_static/src/C/S2-src/strlenptr.c
+.. literalinclude:: /C/S2-src/strlenptr.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -618,7 +618,7 @@ caractères peut se réécrire comme suit.
 
 Les pointeurs sont fréquemment utilisés dans les programmes écrits en langage C et il est important de bien comprendre leur fonctionnement. Un point important à bien comprendre est ce que l'on appelle l'`arithmétique des pointeurs`, c'est-à-dire la façon dont les opérations sur les pointeurs sont exécutées en langage C. Pour cela, il est intéressant de considérer la manipulation d'un tableau d'entiers à travers des pointeurs.
 
-.. literalinclude:: /_static/src/C/src/ptr_arith.c
+.. literalinclude:: /C/src/ptr_arith.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -626,7 +626,7 @@ Les pointeurs sont fréquemment utilisés dans les programmes écrits en langage
 
 En mémoire, ce tableau est stocké en utilisant trois mots consécutifs de 32 bits comme le montre l'exécution du programme ci-dessous :
 
-.. literalinclude:: /_static/src/C/src/ptr_arith.c
+.. literalinclude:: /C/src/ptr_arith.c
    :encoding: utf-8
    :language: c
    :start-after: ///CCC
@@ -640,7 +640,7 @@ En mémoire, ce tableau est stocké en utilisant trois mots consécutifs de 32 b
 
 La même sortie est produite avec le fragment de programme suivant qui utilise un pointeur.
 
-.. literalinclude:: /_static/src/C/src/ptr_arith.c
+.. literalinclude:: /C/src/ptr_arith.c
    :encoding: utf-8
    :language: c
    :start-after: ///EEE
@@ -658,7 +658,7 @@ Après l'exécution de la première ligne, ``ptr`` va contenir l'adresse de l'é
 
 Il est intéressant pour terminer cette première discussion de l'arithmétique des pointeurs, de considérer l'exécution du fragment de code ci-dessous.
 
-.. literalinclude:: /_static/src/C/src/ptr_arith.c
+.. literalinclude:: /C/src/ptr_arith.c
    :encoding: utf-8
    :language: c
    :start-after: ///GGG
@@ -686,7 +686,7 @@ Outre les types de données décrits ci-dessus, les programmes informatiques doi
 
 C permet la définition de structures qui combinent différents types de données simples ou structurés. Contrairement aux langages orientés objet, il n'y a pas de méthode directement associée aux structures qui sont définies. Une structure est uniquement un type de données. Voici quelques exemples de structures simples en C.
 
-.. literalinclude:: /_static/src/C/S2-src/struct.c
+.. literalinclude:: /C/S2-src/struct.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -698,7 +698,7 @@ La structure ``struct fract`` définit une fraction qui est composée de deux en
 
 Les structures permettent de facilement regrouper des données qui sont logiquement reliées entre elles et doivent être manipulées en même temps. C permet d'accéder facilement à un élément d'une structure en utilisant l'opérateur '``.``'. Ainsi, la structure ``point`` dont nous avons parlé ci-dessus aurait pu être initialisée par les trois expressions ci-dessous :
 
-.. literalinclude:: /_static/src/C/S2-src/struct.c
+.. literalinclude:: /C/S2-src/struct.c
    :encoding: utf-8
    :language: c
    :start-after: ///CCC
@@ -724,7 +724,7 @@ Les structures sont également fréquemment utilisées pour représenter des for
 
 La définition de ``struct timeval`` utilise une fonctionnalité fréquemment utilisée du C : la possibilité de définir des alias pour des noms de type de données existants. Cela se fait en utilisant l'opérateur ``typedef``. En C, il est possible de renommer des types de données existants. Ainsi, l'exemple ci-dessous utilise ``typedef`` pour définir ``Entier`` comme alias pour le type ``int`` et ``Fraction`` pour la structure ``struct fraction``.
 
-.. literalinclude:: /_static/src/C/S2-src/typedef.c
+.. literalinclude:: /C/S2-src/typedef.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -739,7 +739,7 @@ Les types ``Entier`` et ``int`` peuvent être utilisés de façon interchangeabl
 
  ``typedef`` est souvent utilisé pour avoir des identifiants de types de données plus courts. Par exemple, il est très courant de remplacer le types ``unsigned`` par les abréviations ci-dessous.
 
-  .. literalinclude:: /_static/src/C/S2-src/typedef.c
+  .. literalinclude:: /C/S2-src/typedef.c
      :encoding: utf-8
      :language: c
      :start-after: ///EEE
@@ -747,7 +747,7 @@ Les types ``Entier`` et ``int`` peuvent être utilisés de façon interchangeabl
 
  Soyez prudents si vous utilisez des ``typedef`` pour redéfinir des pointeurs. En C, il est tout à fait valide d'écrire les lignes suivantes.
 
-  .. literalinclude:: /_static/src/C/S2-src/typedef.c
+  .. literalinclude:: /C/S2-src/typedef.c
      :encoding: utf-8
      :language: c
      :start-after: ///CCC
@@ -758,7 +758,7 @@ Les types ``Entier`` et ``int`` peuvent être utilisés de façon interchangeabl
 
 Les pointeurs sont fréquemment utilisés lors de la manipulation de structures. Lorsqu'un pointeur pointe vers une structure, il est utile de pouvoir accéder facilement aux éléments de la structure. Le langage C supporte deux notations pour représenter ces accès aux éléments d'une structure. La première notation est ``(*ptr).elem``  où ``ptr`` est un pointeur et ``elem`` l'identifiant d'un des éléments de la structure pointée par ``ptr``. Cette notation est en pratique assez peu utilisée. La notation la plus fréquente est ``ptr->elem`` dans laquelle ``ptr`` et ``->elem`` sont respectivement un pointeur et un identifiant d'élément. L'exemple ci-dessous illustre l'initialisation de deux fractions en utilisant ces notations.
 
-.. literalinclude:: /_static/src/C/S2-src/structptr.c
+.. literalinclude:: /C/S2-src/structptr.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -774,7 +774,7 @@ Comme la plupart des langages, le C permet de faciliter la compréhension d'un p
 en le découpant en de nombreuses fonctions. Chacune réalise une
 tâche simple. Tout comme Java, C permet la définition de fonctions qui ne retournent aucun résultat. Celles-ci sont de type ``void`` comme l'exemple trivial ci-dessous.
 
-.. literalinclude:: /_static/src/C/S2-src/fct.c
+.. literalinclude:: /C/S2-src/fct.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -782,7 +782,7 @@ tâche simple. Tout comme Java, C permet la définition de fonctions qui ne reto
 
 La plupart des fonctions utiles retournent un résultat qui peut être une donnée d'un des types standard ou une structure. Cette utilisation est similaire à ce que l'on trouve dans des langages comme Java. Il faut cependant être attentif à la façon dont le langage C traite les arguments des fonctions. Le langage C utilise le `passage par valeur` des arguments. Lorsqu'une fonction est exécutée, elle reçoit les valeurs de ces arguments. Ces valeurs sont stockées dans une zone mémoire qui est locale à la fonction. Toute modification faite sur la valeur d'une variable à l'intérieur d'une fonction est donc locale à cette fonction. Les deux fonctions ci-dessous ont le même résultat et aucune des deux n'a d'effet de bord.
 
-.. literalinclude:: /_static/src/C/S2-src/fct.c
+.. literalinclude:: /C/S2-src/fct.c
    :encoding: utf-8
    :language: c
    :start-after: ///CCC
@@ -790,7 +790,7 @@ La plupart des fonctions utiles retournent un résultat qui peut être une donn
 
 Il faut être nettement plus attentif lorsque l'on écrit des fonctions qui utilisent des pointeurs comme arguments. Lorsqu'une fonction a un argument de type pointeur, celui-ci est passé par valeur, mais connaissant la valeur du pointeur, il est possible à la fonction de modifier le contenu de la zone mémoire pointée par le pointeur. Ceci est illustré par l'exemple ci-dessous.
 
-.. literalinclude:: /_static/src/C/S2-src/fct.c
+.. literalinclude:: /C/S2-src/fct.c
    :encoding: utf-8
    :language: c
    :start-after: ///EEE
@@ -798,13 +798,13 @@ Il faut être nettement plus attentif lorsque l'on écrit des fonctions qui util
 
 Lors de l'exécution de la fonction ``f``, le programme ci-dessus affiche à la console la sortie suivante :
 
-.. literalinclude:: /_static/src/C/S2-src/fct.out
+.. literalinclude:: /C/S2-src/fct.out
    :encoding: utf-8
    :language: console
 
 Cet exemple illustre aussi une contrainte imposée par le langage C sur l'ordre de définition des fonctions. Pour que les fonctions ``times_two`` et ``timestwo`` puissent être utilisées à l'intérieur de la fonction ``f``, il faut qu'elles aient été préalablement définies. Dans l'exemple ci-dessus, cela s'est fait en plaçant la définition des deux fonctions avant leur utilisation. C'est une règle de bonne pratique utilisable pour de petits programmes composés de quelques fonctions. Pour des programmes plus larges, il est préférable de placer au début du code source la signature des fonctions qui y sont définies. La signature d'une fonction comprend le type de valeur de retour de la fonction, son nom et les types de ses arguments. Généralement, ces déclarations sont regroupées à l'intérieur d'un :term:`fichier header` dont le nom se termine par ``.h``.
 
-.. literalinclude:: /_static/src/C/S2-src/fct.h
+.. literalinclude:: /C/S2-src/fct.h
    :encoding: utf-8
    :language: c
    :start-after: ///HHH
@@ -812,7 +812,7 @@ Cet exemple illustre aussi une contrainte imposée par le langage C sur l'ordre
 
 Les fonctions peuvent évidemment recevoir également des tableaux comme arguments. Cela permet par exemple d'implémenter une fonction qui calcule la longueur d'une chaîne de caractères en itérant dessus jusqu'à trouver le caractère de fin de chaîne.
 
-.. literalinclude:: /_static/src/C/S2-src/strlenptr.c
+.. literalinclude:: /C/S2-src/strlenptr.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -821,12 +821,12 @@ Les fonctions peuvent évidemment recevoir également des tableaux comme argumen
 .. spelling::
 
    ième
-                
+
 Tout comme cette fonction peut accéder au `ième` caractère de la chaîne passée en argument, elle peut également et sans aucune restriction modifier chacun des caractères de cette chaîne. Par contre, comme le pointeur vers la chaîne de caractères est passé par valeur, la fonction ne peut pas modifier la zone mémoire qui est pointée par l'argument.
 
 Un autre exemple de fonctions qui manipulent les tableaux sont des fonctions mathématiques qui traitent des vecteurs par exemple.
 
-.. literalinclude:: /_static/src/C/S2-src/fctargs.c
+.. literalinclude:: /C/S2-src/fctargs.c
    :encoding: utf-8
    :language: c
    :start-after: ///CCC
@@ -835,7 +835,7 @@ Un autre exemple de fonctions qui manipulent les tableaux sont des fonctions mat
 
 Ces deux fonctions peuvent être utilisées par le fragment de code ci-dessous :
 
-.. literalinclude:: /_static/src/C/S2-src/fctargs.c
+.. literalinclude:: /C/S2-src/fctargs.c
    :encoding: utf-8
    :language: c
    :start-after: ///EEE
@@ -846,7 +846,7 @@ Ces deux fonctions peuvent être utilisées par le fragment de code ci-dessous :
 
  Certains langages comme Java sont fortement typés et le compilateur contient de nombreuses vérifications, notamment sur les types de données utilisés, qui permettent d'éviter un grand nombre d'erreurs. Le langage C est lui nettement plus libéral. Les premiers compilateurs C étaient très permissifs notamment sur les types de données passés en arguments. Ainsi, un ancien compilateur C accepterait probablement sans broncher les appels suivants :
 
-  .. literalinclude:: /_static/src/C/S2-src/fctargs.c
+  .. literalinclude:: /C/S2-src/fctargs.c
      :encoding: utf-8
      :language: c
      :start-after: ///GGG
@@ -863,7 +863,7 @@ Ces deux fonctions peuvent être utilisées par le fragment de code ci-dessous :
 
 Pour terminer, mentionnons que les fonctions écrites en C peuvent utiliser des structures et des pointeurs vers des structures comme arguments. Elles peuvent aussi retourner des structures comme résultat. Ceci est illustré par deux variantes de fonctions permettant d'initialiser une fraction et de déterminer si deux fractions sont égales [#fegal]_.
 
-.. literalinclude:: /_static/src/C/S2-src/struct.c
+.. literalinclude:: /C/S2-src/struct.c
    :encoding: utf-8
    :language: c
    :start-after: ///EEE
@@ -873,7 +873,7 @@ Considérons d'abord les fonctions ``init`` et ``equal``. ``init`` est une fonct
 
 Les fonctions ``initptr`` et ``equalptr`` utilisent toutes les deux des pointeurs vers des ``struct fraction`` comme arguments. Ce faisant, elles ne peuvent modifier la valeur de ces pointeurs puisqu'ils sont passés comme valeurs. Par contre, les deux fonctions peuvent bien entendu modifier les éléments de la structure qui se trouvent dans la zone de mémoire pointée par le pointeur. C'est ce que ``initptr`` fait pour initialiser la structure. ``equalptr`` par contre se contente d'accéder aux éléments des structures passées en argument sans les modifier. Le fragment de code ci-dessous illustre comment ces fonctions peuvent être utilisées en pratique.
 
-.. literalinclude:: /_static/src/C/S2-src/struct.c
+.. literalinclude:: /C/S2-src/struct.c
    :encoding: utf-8
    :language: c
    :start-after: ///GGG
@@ -932,7 +932,7 @@ A     B      A XOR B
 .. spelling::
 
    De Morgan
-   
+
 
 Ces opérations peuvent être combinées entre elles. Pour des raisons technologiques, les circuits logiques implémentent plutôt les opérations NAND (qui équivaut à AND suivi de NOT) ou NOR (qui équivaut à OR suivi de NOT). Il est également important de mentionner les lois formulées par De Morgan qui peuvent se résumer par les équations suivantes :
 
@@ -941,13 +941,13 @@ Ces opérations peuvent être combinées entre elles. Pour des raisons technolog
 
 Ces opérations binaires peuvent s'étendre à des séquences de bits. Voici quelques exemples qui permettent d'illustrer ces opérations sur des octets.
 
-.. literalinclude:: /_static/src/C/S2-src/exprbin.out
+.. literalinclude:: /C/S2-src/exprbin.out
    :encoding: utf-8
    :language: console
 
 En C, ces expressions logiques s'utilisent comme dans le fragment de code suivant. En général, elles s'utilisent sur des représentations non signées, souvent des ``unsigned char`` ou des ``unsigned int``.
 
-.. literalinclude:: /_static/src/C/S2-src/exprbin.c
+.. literalinclude:: /C/S2-src/exprbin.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -955,7 +955,7 @@ En C, ces expressions logiques s'utilisent comme dans le fragment de code suivan
 
 En pratique, les opérations logiques sont utiles pour effectuer des manipulations au niveau des bits de données stockées en mémoire. Une utilisation fréquente dans certaines applications réseaux ou systèmes est de forcer certains bits à prendre la valeur ``0`` ou ``1``. La conjonction logique permet de forcer facilement un bit à zéro tandis que la disjonction logique permet de forcer facilement un bit à un. L'exemple ci-dessous montre comment forcer les valeurs de certains bits dans un ``unsigned char``. Il peut évidemment se généraliser à des séquences de bits plus longues.
 
-.. literalinclude:: /_static/src/C/S2-src/exprbin.c
+.. literalinclude:: /C/S2-src/exprbin.c
    :encoding: utf-8
    :language: c
    :start-after: ///CCC
@@ -964,10 +964,10 @@ En pratique, les opérations logiques sont utiles pour effectuer des manipulatio
 .. spelling::
 
    Vernam
-                
+
 L'opération XOR joue un rôle important dans certaines applications. La plupart des méthodes de chiffrement et de déchiffrement utilisent de façon extensive cette opération. Une des propriétés intéressantes de l'opération XOR est que :math:`(A \oplus B) \oplus B=A`. Cette propriété est largement utilisée par les méthodes de chiffrement. La méthode développée par Vernam au début du vingtième siècle s'appuie sur l'opération XOR. Pour transmettre un message `M` de façon sûre, elle applique l'opération XOR bit à bit entre tous les bits du message `M` et une clé `K` doit avoir au moins le même nombre de bits que `M`. Si cette clé `K` est totalement aléatoire et n'est utilisée qu'une seule fois, alors on parle de *one-time-pad*. On peut montrer que dans ce cas, la méthode de chiffrement est totalement sûre. En pratique, il est malheureusement difficile d'avoir une clé totalement aléatoire qui soit aussi longue que le message à transmettre. Le programme ci-dessous implémente cette méthode de façon triviale. La fonction `memfrob(3)`_ de la librairie :term:`GNU` utilise également un chiffrement via un XOR.
 
-.. literalinclude:: /_static/src/C/S2-src/xor.c
+.. literalinclude:: /C/S2-src/xor.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -993,7 +993,7 @@ Pour terminer, le langage C supporte des expressions permettant le décalage à
 
 Ces opérations de décalage permettent différentes manipulations de bits. À titre d'exemple, la fonction ``int2bin`` utilise à la fois des décalages et des masques pour calculer la représentation binaire d'un entier non signé et la placer dans une chaîne de caractères.
 
-.. literalinclude:: /_static/src/C/S2-src/exprbin.c
+.. literalinclude:: /C/S2-src/exprbin.c
    :encoding: utf-8
    :language: c
    :start-after: ///EEE
@@ -1016,7 +1016,7 @@ Ces opérations de décalage permettent différentes manipulations de bits. À t
 .. spelling::
 
    IP
-              
+
 .. [#freseau] Parmi les exemples simples, on peut citer la structure ``struct ipv6hdr`` qui correspond à l'entête du protocole IP version 6 et est définie dans `linux/ipv6.h`_.
 
 .. [#fegal] Cette définition de l'égalité entre fractions suppose que les fractions à comparer sont sous forme irréductible. Le lecteur est invité à écrire la fonction générale permettant de tester l'égalité entre fractions réductibles.
diff --git a/Theorie/C/linker.rst b/Theorie/C/linker.rst
index 566866d50795a81aba34f5f15e4b6cddb8279e5d..57405d741c32e6521379530cfab84d512c471c6a 100644
--- a/Theorie/C/linker.rst
+++ b/Theorie/C/linker.rst
@@ -33,7 +33,7 @@ Un premier exemple sont les pointeurs vers des fonctions. Comme nous l'avons vu
 
 Cette application qui supporte plusieurs niveaux de débogage utilise pourtant toujours le même appel pour afficher l'information de débogage : ``(debug_print[debug_level])(...);``. Cet appel profite des pointeurs vers les fonctions. Le tableau ``debug_print`` est un tableau de pointeurs vers des fonctions qui chacune prend comme argument un ``char *``. La variable globale ``debug_level`` est initialisée sur base de l'argument passé au programme.
 
-.. literalinclude:: /_static/src/C/S5-src/fctptr.c
+.. literalinclude:: /C/S5-src/fctptr.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -49,7 +49,7 @@ Ce n'est pas la seule utilisation des pointeurs vers des fonctions. Il y a notam
 
 Le premier est un pointeur vers le début de la zone mémoire à trier. Le second est le nombre d'éléments à trier. Le troisième contient la taille des éléments stockés dans le tableau. Le quatrième argument est un pointeur vers la fonction qui permet de comparer deux éléments du tableau. Cette fonction retourne un entier négatif si son premier argument est inférieur au second et positif ou nul sinon. Un exemple de fonction de comparaison est la fonction `strcmp(3)`_ de la librairie standard. Un autre exemple est repris ci-dessous avec une fonction de comparaison simple qui permet d'utiliser `qsort(3)`_ pour trier un tableau de ``double``.
 
-.. literalinclude:: /_static/src/C/S5-src/qsort.c
+.. literalinclude:: /C/S5-src/qsort.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -60,7 +60,7 @@ Il est utile d'analyser en détails les arguments de la fonction de comparaison
 
 Le second type de pointeurs que nous n'avons pas encore abordé en détails sont les pointeurs vers des pointeurs. En fait, nous les avons utilisés sans vraiment le savoir dans la fonction ``main``. En effet, le second argument de cette fonction est un tableau de pointeurs qui pointent chacun vers des chaînes de caractères différentes. La notation ``char *argv[]`` est équivalente à la notation ``char **argv``. ``**argv`` est donc un pointeur vers une zone qui contient des pointeurs vers des chaînes de caractères. Ce pointeur vers un pointeur doit être utilisé avec précaution. ``argv[0]`` est un pointeur vers une chaîne de caractères. La construction ``&(argv[0])`` permet donc d'obtenir un pointeur vers un pointeur vers une chaîne de caractères, ce qui correspond bien à la déclaration ``char **``. Ensuite, l'utilisation de ``*p`` pourrait surprendre. ``*p`` est un pointeur vers une chaîne de caractères. Il peut donc être comparé à ``NULL`` qui est aussi un pointeur, incrémenté et la chaîne de caractères qu'il référence peut être affichée par `printf(3)`_.
 
-.. literalinclude:: /_static/src/C/S5-src/ptrptr.c
+.. literalinclude:: /C/S5-src/ptrptr.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -82,14 +82,14 @@ L'utilisation principale de `strtol(3)`_ est de convertir une chaîne de caract
 
 `strtol(3)`_ est un exemple de fonction qui doit retourner deux types d'informations. Tout d'abord, `strtol(3)`_ retourne un résultat (dans ce cas un nombre). Si la chaîne de caractères à convertir est erronée, `strtol(3)`_ convertit le début de la chaîne et retourne un pointeur indiquant le premier caractère en erreur. Pour bien comprendre le fonctionnement de `strtol(3)`_, considérons l'exemple ci-dessous.
 
-.. literalinclude:: /_static/src/C/S5-src/strtol.c
+.. literalinclude:: /C/S5-src/strtol.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
 
 Lors de son exécution, ce programme affiche la sortie suivante.
 
-.. literalinclude:: /_static/src/C/S5-src/strtol.out
+.. literalinclude:: /C/S5-src/strtol.out
    :encoding: utf-8
    :language: console
 
@@ -97,7 +97,7 @@ L'appel à `strtol(3)`_ prend trois arguments. Tout d'abord un pointeur vers la
 
 Une implémentation partielle de `strtol(3)`_ pourrait être la suivante.
 
-.. literalinclude:: /_static/src/C/S5-src/mystrtol.c
+.. literalinclude:: /C/S5-src/mystrtol.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -116,7 +116,7 @@ Lorsque l'on développe de grands programmes en C, il est préférable de décou
 
 Pour comprendre l'utilisation de ces modules, considérons d'abord un programme trivial composé de deux modules. Le premier module est celui qui contient la fonction ``main``. Tout programme C doit contenir une fonction ``main`` pour pouvoir être exécuté. C'est en général l'interface avec l'utilisateur. Le second module contient une fonction générique qui est utilisée par le module principal.
 
-.. literalinclude:: /_static/src/C/S5-src/main.c
+.. literalinclude:: /C/S5-src/main.c
    :encoding: utf-8
    :language: c
 
@@ -126,7 +126,7 @@ Un module d'un programme C est en général décomposé en deux parties. Tout d'
  - les constantes qui sont utilisées à l'intérieur du module et doivent être visibles en dehors de celui-ci, notamment par les modules qui utilisent les fonctions du module. Ces constantes peuvent être définies en utilisant des directives ``#define`` du préprocesseur
  - les variables globales qui sont utilisées par les fonctions du module et doivent être accessibles en dehors de celui-ci
 
-.. literalinclude:: /_static/src/C/S5-src/min.h
+.. literalinclude:: /C/S5-src/min.h
    :encoding: utf-8
    :language: c
 
@@ -134,7 +134,7 @@ Un module d'un programme C est en général décomposé en deux parties. Tout d'
 
  L'exemple de :term:`fichier header` ci-dessus illustre une convention courante dans l'écriture de ces fichiers. Parfois, il est nécessaire d'inclure un :term:`fichier header` dans un autre fichier header. Suite à cela, il est possible que les mêmes définitions d'un :term:`fichier header` soient incluses deux fois ou plus dans le même module. Cela peut causer des erreurs de compilation qui risquent de perturber certains programmeurs. Une règle de bonne pratique pour éviter ce problème est d'inclure le contenu du :term:`fichier header` de façon conditionnelle comme présenté ci-dessus. Une constante, dans ce cas ``_MIN_H_``, est définie pour le :term:`fichier header` concerné. Cette constante est définie dans la première ligne effective du :term:`fichier header`. Celui-ci n'est inclus dans un module que si cette constante n'a pas été préalablement définie. Si cette constante est connue par le préprocesseur, cela indique qu'un autre :term:`fichier header` a déjà inclus les définitions de ce fichier et qu'elles ne doivent pas être incluses une seconde fois.
 
-.. literalinclude:: /_static/src/C/S5-src/min.c
+.. literalinclude:: /C/S5-src/min.c
    :encoding: utf-8
    :language: c
 
@@ -144,7 +144,7 @@ Un module d'un programme C est en général décomposé en deux parties. Tout d'
 
 Lorsque l'on doit compiler un programme qui fait appel à plusieurs modules, quelle que soit sa taille, il est préférable d'utiliser `make(1)`_ pour automatiser sa compilation. Le fichier ci-dessous est un petit exemple de :term:`Makefile` utilisable pour un tel projet.
 
-.. literalinclude:: /_static/src/C/S5-src/Makefile2
+.. literalinclude:: /C/S5-src/Makefile2
    :encoding: utf-8
    :language: makefile
    :start-after: ###AAA
@@ -154,7 +154,7 @@ La compilation d'un tel programme se déroule en plusieurs étapes. La première
 
 La figure ci-dessous représente graphiquement les différentes étapes de compilation des modules ``min.c`` et ``main.c``.
 
-.. figure:: /_static/figures/C/figures/figures-007-c.png
+.. figure:: /C/figures/figures-007-c.png
    :align: center
    :scale: 60
 
@@ -176,17 +176,17 @@ Il faut noter que ``static`` peut aussi précéder des déclarations de fonction
 
 Afin d'illustrer l'utilisation de ``static`` et ``extern``, considérons le programme ``prog.c`` ci-dessous qui inclut le module ``module.c`` et également le module ``min.c`` présenté plus haut.
 
-.. literalinclude:: /_static/src/C/S5-src/module.h
+.. literalinclude:: /C/S5-src/module.h
    :encoding: utf-8
    :language: c
 
-.. literalinclude:: /_static/src/C/S5-src/module.c
+.. literalinclude:: /C/S5-src/module.c
    :encoding: utf-8
    :language: c
 
 Ce module contient deux fonctions, ``vmin`` et ``min``. ``vmin`` est accessible depuis n'importe quel module. Sa signature est reprise dans le :term:`fichier header` ``module.h``. La fonction ``min`` par contre est déclarée comme étant ``static``. Cela implique qu'elle n'est utilisable qu'à l'intérieur de ce module et invisible de tout autre module. La variable globale ``num1`` est accessible depuis n'importe quel module. La variable ``num2`` également, mais elle est initialisée dans un autre module. Enfin, la variable ``num3`` n'est accessible qu'à l'intérieur de ce module.
 
-.. literalinclude:: /_static/src/C/S5-src/prog.c
+.. literalinclude:: /C/S5-src/prog.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -195,7 +195,7 @@ Ce module inclus les fichiers ``min.h`` et ``module.h`` qui contiennent les sign
 
 La fonction ``f`` mérite que l'on s'y attarde un peu. Cette fonction contient la définition de la variable ``static n``. Même si cette variable est locale à la fonction ``f`` et donc invisible en dehors de cette fonction, le compilateur va lui réserver une place dans la même zone que les variables globales. La valeur de cette variable ``static`` sera initialisée une seule fois : au démarrage du programme. Même si cette variable parait être locale, elle ne sera jamais réinitialisée lors d'un appel à la fonction ``f``. Comme cette variable est stockée en dehors de la pile, elle conserve sa valeur d'une invocation à l'autre de la fonction ``f``. Ceci est illustré par l'exécution du programme qui produit la sortie suivante.
 
-.. literalinclude:: /_static/src/C/S5-src/prog.out
+.. literalinclude:: /C/S5-src/prog.out
    :encoding: utf-8
    :language: console
 
@@ -211,7 +211,7 @@ Les systèmes Unix utilisent la variable globale :term:`errno` pour résoudre ce
 
 A titre d'exemple, le programme ci-dessous utilise `strerror(3)`_ pour afficher un message d'erreur plus parlant lors d'appels erronés à la fonction `setenv(3)`_.
 
-.. literalinclude:: /_static/src/C/S5-src/errno.c
+.. literalinclude:: /C/S5-src/errno.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
diff --git a/Theorie/C/malloc.rst b/Theorie/C/malloc.rst
index cc72068024d5d710e212c70e6fe09aeb38b1d054..940802fc1b1a4c30ad97c525af47692a32c52ee7 100644
--- a/Theorie/C/malloc.rst
+++ b/Theorie/C/malloc.rst
@@ -30,9 +30,9 @@ La première notion importante concernant la déclaration des variables est leur
 Dans un fichier donné, il ne peut évidemment pas y avoir deux variables globales qui ont le même identifiant. Lorsqu'une variable est définie dans un `bloc`, la portée de cette variable est locale à ce bloc. On parle dans ce cas de :term:`portée locale`. La variable locale n'existe pas avant le début du bloc et n'existe plus à la fin du bloc. Contrairement aux identifiants de variables globales qui doivent être uniques à l'intérieur d'un fichier, il est possible d'avoir plusieurs variables locales qui ont le même identifiant à l'intérieur d'un fichier. C'est fréquent notamment pour les définitions d'arguments de fonction et les variables de boucles. Dans l'exemple ci-dessus, les variables ``n`` et ``j`` ont une portée locale. La variable ``j`` est définie dans deux blocs différents à l'intérieur de la fonction ``f``.
 
 
-Le programme :download:`/_static/src/C/S3-src/portee.c` illustre la façon dont le compilateur C gère la portée de différentes variables.
+Le programme :download:`/C/S3-src/portee.c` illustre la façon dont le compilateur C gère la portée de différentes variables.
 
-.. literalinclude:: /_static/src/C/S3-src/portee.c
+.. literalinclude:: /C/S3-src/portee.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -42,7 +42,7 @@ Ce programme contient deux variables qui ont une portée globale : ``g1`` et ``g
 
 Lorsqu'un identifiant de variable locale est utilisé à plusieurs endroits dans un fichier, c'est la définition la plus proche qui est utilisée. L'exécution du programme ci-dessus illustre cette utilisation des variables globales et locales.
 
-.. literalinclude:: /_static/src/C/S3-src/portee.out
+.. literalinclude:: /C/S3-src/portee.out
    :encoding: utf-8
    :language: console
 
@@ -52,14 +52,14 @@ Lorsqu'un identifiant de variable locale est utilisé à plusieurs endroits dans
 
 Les versions récentes de C [C99]_ permettent également de définir des variables dont la valeur sera constante durant toute l'exécution du programme. Ces déclarations de ces constants sont préfixées par le mot-clé ``const`` qui joue le même rôle que le mot clé ``final`` en Java.
 
-.. literalinclude:: /_static/src/C/S3-src/const.c
+.. literalinclude:: /C/S3-src/const.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
    :end-before: ///BBB
 
 
-Il y a deux façons de définir des constantes dans les versions récentes de C [C99]_. La première est via la macro ``#define`` du préprocesseur. Cette macro permet de remplacer une chaîne de caractères (par exemple ``M_PI`` qui provient de `math.h`_) par un nombre ou une autre chaîne de caractères. Ce remplacement s'effectue avant la compilation. Dans le cas de ``M_PI`` ci-dessus, le préprocesseur remplace toute les occurrences de cette chaîne de caractères par la valeur numérique de :math:`\pi`. Lorsqu'une variable ``const`` est utilisée, la situation est un peu différente. Le préprocesseur n'intervient pas. Par contre, le compilateur réserve une zone mémoire pour la variable qui a été définie comme constante. Cela a deux avantages par rapport à l'utilisation de ``#define``. Premièrement, il est possible de définir comme constante n'importe quel type de données en C, y compris des structures ou des pointeurs alors qu'avec un ``#define`` on ne peut définir que des nombres ou des chaînes de caractères. Ensuite, comme une ``const`` est stockée en mémoire, il est possible d'obtenir son adresse et de l'examiner via un :term:`debugger`.
+Il y a deux façons de définir des constantes dans les versions récentes de C [C99]_. La première est via la macro ``#define`` du préprocesseur. Cette macro permet de remplacer une chaîne de caractères (par exemple ``M_PI`` qui provient de `math.h`_) par un nombre ou une autre chaîne de caractères. Ce remplacement s'effectue avant la compilation. Dans le cas de ``M_PI`` ci-dessus, le préprocesseur remplace toute les occurrences de cette chaîne de caractères par la valeur numérique de :math:`\pi`. Lorsqu'une variable ``const`` est utilisée, la situation est un peu différente. Le préprocesseur n'intervient pas. Par contre, le compilateur réserve une zone mémoire pour la variable qui a été définie comme constante. Cela a deux avantages par rapport à l'utilisation de ``#define``. Premièrement, il est possible de définir comme constante n'importe quel type de données en C, y compris des structures ou des pointeurs alors qu'avec un ``#define`` on ne pe//ut définir que des nombres ou des chaînes de caractères. Ensuite, comme une ``const`` est stockée en mémoire, il est possible d'obtenir son adresse et de l'examiner via un :term:`debugger`.
 
 
 Unions et énumérations
@@ -67,7 +67,7 @@ Unions et énumérations
 
 Les structures que nous avons présentées précédemment permettent de combiner plusieurs données de types primitifs différents entre elles. Outre ces structures (``struct``), le langage C supporte également les ``enum`` et les ``union``. Le mot-clé ``enum`` est utilisé pour définir un type énuméré, c'est-à-dire un type de donnée qui permet de stocker un nombre fixe de valeurs. Quelques exemples classiques sont repris dans le fragment de programme ci-dessous :
 
-.. literalinclude:: /_static/src/C/S3-src/enum.c
+.. literalinclude:: /C/S3-src/enum.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -75,7 +75,7 @@ Les structures que nous avons présentées précédemment permettent de combiner
 
 Le premier ``enum`` permet de définir le type de données ``day`` qui contient une valeur énumérée pour chaque jour de la semaine. L'utilisation d'un type énuméré rend le code plus lisible que simplement l'utilisation de constantes définies via le préprocesseur.
 
-.. literalinclude:: /_static/src/C/S3-src/enum.c
+.. literalinclude:: /C/S3-src/enum.c
    :encoding: utf-8
    :language: c
    :start-after: ///CCC
@@ -85,7 +85,7 @@ En pratique, lors de la définition d'un type énuméré, le compilateur C assoc
 
 Outre les structures, le langage C supporte également les unions. Alors qu'une structure permet de stocker plusieurs données dans une même zone mémoire, une ``union`` permet de réserver une zone mémoire pour stocker une données parmi plusieurs types possibles. Une ``union`` est parfois utilisée pour minimiser la quantité de mémoire utilisée pour une structure de données qui peut contenir des données de plusieurs types. Pour bien comprendre la différence entre une ``union`` et une ``struct``, considérons l'exemple ci-dessous.
 
-.. literalinclude:: /_static/src/C/S3-src/union.c
+.. literalinclude:: /C/S3-src/union.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -94,7 +94,7 @@ Outre les structures, le langage C supporte également les unions. Alors qu'une
 
 Une union, ``u`` et une structure, ``s`` sont déclarées dans ce fragment de programme.
 
-.. literalinclude:: /_static/src/C/S3-src/union.c
+.. literalinclude:: /C/S3-src/union.c
    :encoding: utf-8
    :language: c
    :start-after: ///CCC
@@ -103,7 +103,7 @@ Une union, ``u`` et une structure, ``s`` sont déclarées dans ce fragment de pr
 La structure ``s`` peut contenir à la fois un entier et un caractère. Par contre, l'``union`` ``u``, peut elle contenir un entier (``u.i``) *ou* un caractère (``u.c``), mais jamais les deux en même temps.
 Le compilateur C alloue la taille pour l'``union`` de façon à ce qu'elle puisse contenir le type de donnée se trouvant dans l'``union`` nécessitant le plus de mémoire. Si les unions sont utiles dans certains cas très particulier, il faut faire très attention à leur utilisation. Lorsqu'une ``union`` est utilisée, le compilateur C fait encore moins de vérifications sur les types de données et le code ci-dessous est considéré comme valide par le compilateur :
 
-.. literalinclude:: /_static/src/C/S3-src/union.c
+.. literalinclude:: /C/S3-src/union.c
    :encoding: utf-8
    :language: c
    :start-after: ///EEE
@@ -111,7 +111,7 @@ Le compilateur C alloue la taille pour l'``union`` de façon à ce qu'elle puiss
 
 Lors de son exécution, la zone mémoire correspondant à l'union ``u`` sera simplement interprétée comme contenant un ``char``, même si on vient d'y stocker un entier. En pratique, lorsqu'une ``union`` est vraiment nécessaire pour des raisons d'économie de mémoire, on préférera la placer dans une ``struct`` en utilisant un type énuméré qui permet de spécifier le type de données qui est présent dans l'``union``.
 
-.. literalinclude:: /_static/src/C/S3-src/union.c
+.. literalinclude:: /C/S3-src/union.c
    :encoding: utf-8
    :language: c
    :start-after: ///BBB
@@ -119,7 +119,7 @@ Lors de son exécution, la zone mémoire correspondant à l'union ``u`` sera sim
 
 Le programmeur pourra alors utiliser cette structure en indiquant explicitement le type de données qui y est actuellement stocké comme suit.
 
-.. literalinclude:: /_static/src/C/S3-src/union.c
+.. literalinclude:: /C/S3-src/union.c
    :encoding: utf-8
    :language: c
    :start-after: ///FFF
@@ -131,95 +131,94 @@ Organisation de la mémoire
 
 Lors de l'exécution d'un programme en mémoire, le système d'exploitation charge depuis le système de fichier le programme en langage machine et le place à un endroit convenu en mémoire. Lorsqu'un programme s'exécute sur un système Unix, la mémoire peut être vue comme étant divisée en six zones principales. Ces zones sont représentées schématiquement dans la figure ci-dessous.
 
-.. figure:: /_static/figures/C/figures/figures-001-c.png
+.. figure:: /C/figures/figures-001-c.png
    :align: center
 
    Organisation d'un programme Linux en mémoire
 
-.. La figure ci-dessus présente une vision schématique de la façon dont un processus Linux est organisé en mémoire centrale. 
-Dans le cadre de ce cours, nous nous concentrerons sur les zones du Stack et du Heap.
+.. La figure ci-dessus présente une vision schématique de la façon dont un processus Linux est organisé en mémoire centrale.
 
-.. Il y a d'abord une partie de la mémoire qui est réservée au système d'exploitation (OS dans la figure). Cette zone est représentée en grisé dans la figure.
+Il y a d'abord une partie de la mémoire qui est réservée au système d'exploitation (OS dans la figure). Cette zone est représentée en grisé dans la figure.
 
-..
-    Le segment text
-    ---------------
 
-    La première zone est appelée par convention le :term:`segment text`. Cette zone se situe dans la partie basse de la mémoire [#fetext]_. C'est dans cette zone que sont stockées toutes les instructions qui sont exécutées par le micro-processeur. Elle est généralement considérée par le système d'exploitation comme étant uniquement accessible en lecture. Si un programme tente de modifier son :term:`segment text`, il sera immédiatement interrompu par le système d'exploitation. C'est dans le segment text que l'on retrouvera les instructions de langage machine correspondant aux fonctions de calcul et d'affichage du programme. Nous en reparlerons lorsque nous présenterons le fonctionnement du langage d'assemblage.
+Le segment text
+---------------
 
-    Le segment des données initialisées
-    -----------------------------------
+La première zone est appelée par convention le :term:`segment text`. Cette zone se situe dans la partie basse de la mémoire [#fetext]_. C'est dans cette zone que sont stockées toutes les instructions qui sont exécutées par le micro-processeur. Elle est généralement considérée par le système d'exploitation comme étant uniquement accessible en lecture. Si un programme tente de modifier son :term:`segment text`, il sera immédiatement interrompu par le système d'exploitation. C'est dans le segment text que l'on retrouvera les instructions de langage machine correspondant aux fonctions de calcul et d'affichage du programme. Nous en reparlerons lorsque nous présenterons le fonctionnement du langage d'assemblage.
 
-    La deuxième zone, baptisée :term:`segment des données initialisées`, contient l'ensemble des données et chaînes de caractères qui sont utilisées dans le programme. Ce segment contient deux types de données. Tout d'abord, il comprend l'ensemble des variables globales explicitement initialisées par le programme (dans le cas contraire, elles sont initialisées à zéro par le compilateur et appartiennent alors au :term:`segment des données non-initialisées`). Ensuite, les constantes et les chaînes de caractères utilisées par le programme.
+Le segment des données initialisées
+-----------------------------------
 
-    .. literalinclude:: /C/S3-src/dataseg.c
-       :encoding: utf-8
-       :language: c
-       :start-after: ///AAA
-       :end-before: ///BBB
+La deuxième zone, baptisée :term:`segment des données initialisées`, contient l'ensemble des données et chaînes de caractères qui sont utilisées dans le programme. Ce segment contient deux types de données. Tout d'abord, il comprend l'ensemble des variables globales explicitement initialisées par le programme (dans le cas contraire, elles sont initialisées à zéro par le compilateur et appartiennent alors au :term:`segment des données non-initialisées`). Ensuite, les constantes et les chaînes de caractères utilisées par le programme.
 
-    Dans le programme ci-dessus, la variable ``g_init``, la constante ``un`` et les tableaux ``tab`` et ``cours`` sont dans la zone réservée aux variables initialisées. En pratique, leur valeur d'initialisation sera chargée depuis le fichier exécutable lors de son chargement en mémoire. Il en va de même pour toutes les chaînes de caractères qui sont utilisées comme arguments aux appels à ``printf(3)``.
+.. literalinclude:: /C/S3-src/dataseg.c
+   :encoding: utf-8
+   :language: c
+   :start-after: ///AAA
+   :end-before: ///BBB
 
-    L'exécution de ce programme produit la sortie standard suivante.
+Dans le programme ci-dessus, la variable ``g_init``, la constante ``un`` et les tableaux ``tab`` et ``cours`` sont dans la zone réservée aux variables initialisées. En pratique, leur valeur d'initialisation sera chargée depuis le fichier exécutable lors de son chargement en mémoire. Il en va de même pour toutes les chaînes de caractères qui sont utilisées comme arguments aux appels à ``printf(3)``.
 
-    .. literalinclude:: /C/S3-src/dataseg.out
-       :encoding: utf-8
-       :language: console
+L'exécution de ce programme produit la sortie standard suivante.
+
+.. literalinclude:: /C/S3-src/dataseg.out
+   :encoding: utf-8
+   :language: console
 
 
-    Cette sortie illustre bien les adresses où les variables globales sont stockées. La variable globale ``msg`` fait notamment partie du :term:`segment des données non-initialisées`.
+Cette sortie illustre bien les adresses où les variables globales sont stockées. La variable globale ``msg`` fait notamment partie du :term:`segment des données non-initialisées`.
 
-    Le segment des données non-initialisées
-    ---------------------------------------
+Le segment des données non-initialisées
+---------------------------------------
 
-    La troisième zone est le :term:`segment des données non-initialisées`, réservée aux variables non-initialisées. Cette zone mémoire est initialisée à zéro par le système d'exploitation lors du démarrage du programme. Dans l'exemple ci-dessus, c'est dans cette zone que l'on stockera les valeurs de la variable ``g`` et des tableaux ``array`` et ``msg``.
+La troisième zone est le :term:`segment des données non-initialisées`, réservée aux variables non-initialisées. Cette zone mémoire est initialisée à zéro par le système d'exploitation lors du démarrage du programme. Dans l'exemple ci-dessus, c'est dans cette zone que l'on stockera les valeurs de la variable ``g`` et des tableaux ``array`` et ``msg``.
 
-    .. note:: Initialisation des variables
+.. note:: Initialisation des variables
 
-     Un point important auquel tout programmeur C doit faire attention est l'initialisation correcte de l'ensemble des variables utilisées dans un programme. Le compilateur C est nettement plus permissif qu'un compilateur Java et il autorisera l'utilisation de variables avant qu'elles n'aient été explicitement initialisées, ce qui peut donner lieu à des erreurs parfois très difficiles à corriger.
+Un point important auquel tout programmeur C doit faire attention est l'initialisation correcte de l'ensemble des variables utilisées dans un programme. Le compilateur C est nettement plus permissif qu'un compilateur Java et il autorisera l'utilisation de variables avant qu'elles n'aient été explicitement initialisées, ce qui peut donner lieu à des erreurs parfois très difficiles à corriger.
 
-     En C, par défaut les variables globales qui ne sont pas explicitement initialisées dans un programme sont initialisées à la valeur zéro par le compilateur. Plus précisément, la zone mémoire qui correspond à chaque variable globale non-explicitement initialisée contiendra des bits valant 0. Pour les variables locales, le langage C n'impose aucune initialisation par défaut au compilateur. Par souci de performance et sachant qu'un programmeur ne devrait jamais utiliser de variable locale non explicitement initialisée, le compilateur C n'initialise pas par défaut la valeur de ces variables. Cela peut avoir des conséquences ennuyeuses comme le montre l'exemple ci-dessous.
+En C, par défaut les variables globales qui ne sont pas explicitement initialisées dans un programme sont initialisées à la valeur zéro par le compilateur. Plus précisément, la zone mémoire qui correspond à chaque variable globale non-explicitement initialisée contiendra des bits valant 0. Pour les variables locales, le langage C n'impose aucune initialisation par défaut au compilateur. Par souci de performance et sachant qu'un programmeur ne devrait jamais utiliser de variable locale non explicitement initialisée, le compilateur C n'initialise pas par défaut la valeur de ces variables. Cela peut avoir des conséquences ennuyeuses comme le montre l'exemple ci-dessous.
 
-     .. literalinclude:: /C/S3-src/initvar.c
-        :encoding: utf-8
-        :language: c
-        :start-after: ///AAA
-        :end-before: ///BBB
+.. literalinclude:: /C/S3-src/initvar.c
+   :encoding: utf-8
+   :language: c
+   :start-after: ///AAA
+   :end-before: ///BBB
 
-     Cet extrait de programme contient deux fonctions erronées. La seconde, baptisée ``read(void)`` déclare un tableau local et retourne la somme des éléments de ce tableau sans l'initialiser. En Java, une telle utilisation d'un tableau non-initialisé serait détectée par le compilateur. En C, elle est malheureusement valide (mais fortement découragée évidemment). La première fonction, ``init(void)`` se contente d'initialiser un tableau local mais ne retourne aucun résultat. Cette fonction ne sert a priori à rien puisqu'elle n'a aucun effet sur les variables globales et ne retourne aucun résultat. L'exécution de ces fonctions via le fragment de code ci-dessous donne cependant un résultat interpellant.
+Cet extrait de programme contient deux fonctions erronées. La seconde, baptisée ``read(void)`` déclare un tableau local et retourne la somme des éléments de ce tableau sans l'initialiser. En Java, une telle utilisation d'un tableau non-initialisé serait détectée par le compilateur. En C, elle est malheureusement valide (mais fortement découragée évidemment). La première fonction, ``init(void)`` se contente d'initialiser un tableau local mais ne retourne aucun résultat. Cette fonction ne sert a priori à rien puisqu'elle n'a aucun effet sur les variables globales et ne retourne aucun résultat. L'exécution de ces fonctions via le fragment de code ci-dessous donne cependant un résultat interpellant.
 
-     .. literalinclude:: /C/S3-src/initvar.c
-        :encoding: utf-8
-        :language: c
-        :start-after: ///CCC
-        :end-before: ///DDD
+.. literalinclude:: /C/S3-src/initvar.c
+   :encoding: utf-8
+   :language: c
+   :start-after: ///CCC
+   :end-before: ///DDD
 
-     .. literalinclude:: /C/S3-src/initvar.out
-        :encoding: utf-8
-        :language: console
+.. literalinclude:: /C/S3-src/initvar.out
+   :encoding: utf-8
+   :language: console
 
-    Les arguments et variables d'environnement
-    ------------------------------------------
+Les arguments et variables d'environnement
+------------------------------------------
 
-    Lorsque le système d'exploitation charge un programme Unix en mémoire, il initialise dans le haut de la mémoire une zone qui contient deux types de variables. Cette zone contient tout d'abord les arguments qui ont été passés via la ligne de commande. Le système d'exploitation met dans ``argc`` le nombre d'arguments et place dans ``char *argv[]`` tous les arguments passés avec dans ``argv[0]`` le nom du programme qui est exécuté.
+Lorsque le système d'exploitation charge un programme Unix en mémoire, il initialise dans le haut de la mémoire une zone qui contient deux types de variables. Cette zone contient tout d'abord les arguments qui ont été passés via la ligne de commande. Le système d'exploitation met dans ``argc`` le nombre d'arguments et place dans ``char *argv[]`` tous les arguments passés avec dans ``argv[0]`` le nom du programme qui est exécuté.
 
-    Cette zone contient également les variables d'environnement. Ces variables sont généralement relatives à la configuration du système. Leurs valeurs sont définies par l'administrateur système ou l'utilisateur. De nombreuses variables d'environnement sont utilisées dans les systèmes Unix. Elles servent à modifier le comportement de certains programmes. Une liste exhaustive de toutes les variables d'environnement est impossible, mais en voici quelques unes qui sont utiles en pratique [#fenvbash]_:
+Cette zone contient également les variables d'environnement. Ces variables sont généralement relatives à la configuration du système. Leurs valeurs sont définies par l'administrateur système ou l'utilisateur. De nombreuses variables d'environnement sont utilisées dans les systèmes Unix. Elles servent à modifier le comportement de certains programmes. Une liste exhaustive de toutes les variables d'environnement est impossible, mais en voici quelques unes qui sont utiles en pratique [#fenvbash]_:
 
-     - ``HOSTNAME`` : le nom de la machine sur laquelle le programme s'exécute. Ce nom est fixé par l'administrateur système via la commande `hostname(1)`_
-     - ``SHELL`` : l'interpréteur de commande utilisé par défaut pour l'utilisateur courant. Cet interpréteur est lancé par le système au démarrage d'une session de l'utilisateur. Il est stocké dans le fichier des mots de passe et peut être modifié par l'utilisateur via la commande `passwd(1)`_
-     - ``USER`` : le nom de l'utilisateur courant. Sous Unix, chaque utilisateur est identifié par un numéro d'utilisateur et un nom uniques. Ces identifiants sont fixés par l'administrateur système via la commande `passwd(1)`_
-     - ``HOME``: le répertoire d'accueil de l'utilisateur courant. Ce répertoire d'accueil appartient à l'utilisateur. C'est dans ce répertoire qu'il peut stocker tous ses fichiers.
-     - ``PRINTER`` : le nom de l'imprimante par défaut qui est utilisée par la commande `lp(1posix)`_
-     - ``PATH``: cette variable d'environnement contient la liste ordonnée des répertoires que le système parcourt pour trouver un programme à exécuter. Cette liste contient généralement les répertoires dans lesquels le système stocke les exécutables standards, comme ``/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:`` ainsi que des répertoires relatifs à des programmes spécialisés comme ``/usr/lib/mozart/bin:/opt/python3/bin``. L'utilisateur peut ajouter des répertoires à son ``PATH`` avec `bash(1)`_ en incluant par exemple la commande ``PATH=$PATH:$HOME/local/bin:.`` dans son fichier ``.profile``. Cette commande ajoute au ``PATH`` par défaut le répertoire ``$HOME/local/bin`` et le répertoire courant. Par convention, Unix utilise le caractère ``.`` pour représenter ce répertoire courant.
+- ``HOSTNAME`` : le nom de la machine sur laquelle le programme s'exécute. Ce nom est fixé par l'administrateur système via la commande `hostname(1)`_
+- ``SHELL`` : l'interpréteur de commande utilisé par défaut pour l'utilisateur courant. Cet interpréteur est lancé par le système au démarrage d'une session de l'utilisateur. Il est stocké dans le fichier des mots de passe et peut être modifié par l'utilisateur via la commande `passwd(1)`_
+- ``USER`` : le nom de l'utilisateur courant. Sous Unix, chaque utilisateur est identifié par un numéro d'utilisateur et un nom uniques. Ces identifiants sont fixés par l'administrateur système via la commande `passwd(1)`_
+- ``HOME``: le répertoire d'accueil de l'utilisateur courant. Ce répertoire d'accueil appartient à l'utilisateur. C'est dans ce répertoire qu'il peut stocker tous ses fichiers.
+- ``PRINTER`` : le nom de l'imprimante par défaut qui est utilisée par la commande `lp(1posix)`_
+- ``PATH``: cette variable d'environnement contient la liste ordonnée des répertoires que le système parcourt pour trouver un programme à exécuter. Cette liste contient généralement les répertoires dans lesquels le système stocke les exécutables standards, comme ``/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:`` ainsi que des répertoires relatifs à des programmes spécialisés comme ``/usr/lib/mozart/bin:/opt/python3/bin``. L'utilisateur peut ajouter des répertoires à son ``PATH`` avec `bash(1)`_ en incluant par exemple la commande ``PATH=$PATH:$HOME/local/bin:.`` dans son fichier ``.profile``. Cette commande ajoute au ``PATH`` par défaut le répertoire ``$HOME/local/bin`` et le répertoire courant. Par convention, Unix utilise le caractère ``.`` pour représenter ce répertoire courant.
 
-    La librairie standard contient plusieurs fonctions qui permettent de manipuler les variables d'environnement d'un processus. La fonction `getenv(3)`_ permet de récupérer la valeur associée à une variable d'environnement. La fonction `unsetenv(3)`_ permet de supprimer une variable de l'environnement du programme courant. La fonction `setenv(3)`_ permet elle de modifier la valeur d'une variable d'environnement. Cette fonction alloue de la mémoire pour stocker la nouvelle variable d'environnement et peut échouer si il n'y a pas assez de mémoire disponible pour stocker de nouvelles variables d'environnement. Ces fonctions sont utilisées notamment par l'interpréteur de commande mais parfois par des programmes dont le comportement dépend de la valeur de certaines variables d'environnement. Par exemple, la commande `man(1)`_ utilise différentes variables d'environnement pour déterminer par exemple où les pages de manuel sont stockées et la langue (variable ``LANG``) dans laquelle il faut afficher les pages de manuel.
+La librairie standard contient plusieurs fonctions qui permettent de manipuler les variables d'environnement d'un processus. La fonction `getenv(3)`_ permet de récupérer la valeur associée à une variable d'environnement. La fonction `unsetenv(3)`_ permet de supprimer une variable de l'environnement du programme courant. La fonction `setenv(3)`_ permet elle de modifier la valeur d'une variable d'environnement. Cette fonction alloue de la mémoire pour stocker la nouvelle variable d'environnement et peut échouer si il n'y a pas assez de mémoire disponible pour stocker de nouvelles variables d'environnement. Ces fonctions sont utilisées notamment par l'interpréteur de commande mais parfois par des programmes dont le comportement dépend de la valeur de certaines variables d'environnement. Par exemple, la commande `man(1)`_ utilise différentes variables d'environnement pour déterminer par exemple où les pages de manuel sont stockées et la langue (variable ``LANG``) dans laquelle il faut afficher les pages de manuel.
 
-    Le programme ci-dessous illustre brièvement l'utilisation de `getenv(3)`_, `unsetenv(3)`_ et `setenv(3)`_. Outre ces fonctions, il existe également `clearenv(3)`_ qui permet d'effacer complètement toutes les variables d'environnement du programme courant et `putenv(3)`_ qui était utilisé avant `setenv(3)`_.
+Le programme ci-dessous illustre brièvement l'utilisation de `getenv(3)`_, `unsetenv(3)`_ et `setenv(3)`_. Outre ces fonctions, il existe également `clearenv(3)`_ qui permet d'effacer complètement toutes les variables d'environnement du programme courant et `putenv(3)`_ qui était utilisé avant `setenv(3)`_.
 
-    .. literalinclude:: /C/S3-src/argv-env.c
-       :encoding: utf-8
-       :language: c
-       :start-after: ///AAA
+.. literalinclude:: /C/S3-src/argv-env.c
+   :encoding: utf-8
+   :language: c
+   :start-after: ///AAA
 
 La pile (ou stack)
 ------------------
@@ -285,7 +284,7 @@ La fonction `malloc(3)`_ prend comme argument la taille (en bytes) de la zone m
 
  Comme le langage Java, le langage C supporte des conversions implicites et explicites entre les différents types de données. Ces conversions sont possibles entre les types primitifs et les pointeurs. Nous les rencontrerons régulièrement, par exemple lorsqu'il faut récupérer un pointeur alloué par `malloc(3)`_ ou le résultat de ``sizeof``. Contrairement au compilateur Java, le compilateur C n'émet pas toujours de message de :term:`warning` lors de l'utilisation de  typecast qui risque d'engendrer une perte de précision. Ce problème est illustré par l'exemple suivant avec les nombres.
 
-  .. literalinclude:: /_static/src/C/S3-src/typecast.c
+  .. literalinclude:: /C/S3-src/typecast.c
      :encoding: utf-8
      :language: c
      :start-after: ///AAA
@@ -296,7 +295,7 @@ La fonction de la librairie `free(3)`_ est le pendant de `malloc(3)`_. Elle perm
 
 Le programme ci-dessous illustre l'utilisation de `malloc(3)`_ et `free(3)`_.
 
-.. literalinclude:: /_static/src/C/S3-src/malloc.c
+.. literalinclude:: /C/S3-src/malloc.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -304,7 +303,7 @@ Le programme ci-dessous illustre l'utilisation de `malloc(3)`_ et `free(3)`_.
 
 Ce programme alloue trois zones mémoires. Le pointeur vers la première est sauvé dans le pointeur ``string``. Elle est destinée à contenir une chaîne de ``size`` caractères (avec un caractère supplémentaire pour stocker le caractère ``\0`` de fin de chaîne). Il y a deux points à remarquer concernant cette allocation. Tout d'abord, le pointeur retourné par `malloc(3)`_ est "casté" en un ``char *``. Cela indique au compilateur que ``string`` va bien contenir un pointeur vers une chaîne de caractères. Cette conversion explicite rend le programme plus clair. Ensuite, la valeur de retour de `malloc(3)`_  est systématiquement testée. `malloc(3)`_ peut en effet retourner ``NULL`` lorsque la mémoire est remplie. Cela a peu de chance d'arriver dans un programme de test tel que celui-ci, mais tester les valeurs de retour des fonctions de la librairie est une bonne habitude à prendre lorsque l'on programme sous Unix. Le second pointeur, ``vector`` pointe vers une zone destiné à contenir un tableau d'entiers. Le dernier pointeur, ``fract_vect`` pointe vers une zone qui pourra stocker un tableau de ``Fraction``. Lors de son exécution, le programme affiche la sortie suivante.
 
-.. literalinclude:: /_static/src/C/S3-src/malloc.out
+.. literalinclude:: /C/S3-src/malloc.out
    :encoding: utf-8
    :language: console
 
@@ -313,7 +312,7 @@ Dans cette sortie, on remarque que l'appel à fonction `free(3)`_ libère la zon
 Un autre exemple d'utilisation de `malloc(3)`_ est la fonction ``duplicate`` ci-dessous qui permet de retourner une copie d'une chaîne de caractères. Il est important de noter qu'en C la fonction `strlen(3)`_ retourne la longueur de la chaîne de caractères passée en argument sans prendre en compte le caractère ``\0`` qui marque sa fin. C'est la raison pour laquelle `malloc(3)`_ doit réserver un bloc de mémoire en plus. Même si généralement les ``char`` occupent un octet en mémoire, il est préférable d'utiliser explicitement ``sizeof(char)`` lors du calcul de l'espace mémoire nécessaire pour un type de données.
 
 
-.. literalinclude:: /_static/src/C/S3-src/strcpy.c
+.. literalinclude:: /C/S3-src/strcpy.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -337,7 +336,7 @@ Lors de la compilation, `gcc(1)`_ affiche le :term:`warning` ``In function ‘du
 `malloc(3)`_ et `free(3)`_ sont fréquemment utilisés dans des programmes qui manipulent des structures de données dont la taille varie dans le temps. C'est le cas pour les différents sortes de listes chaînées, les piles, les queues, les arbres, ... L'exemple ci-dessous (:download:`/C/S3-src/stack.c`) illustre une implémentation d'une pile simple en C. Le pointeur vers le sommet de la pile est défini comme une variable globale. Chaque élément de la pile est représenté comme un pointeur vers une structure qui contient un pointeur vers la donnée stockée (dans cet exemple des fractions) et l'élément suivant sur la pile. Les fonctions ``push`` et ``pop`` permettent respectivement d'ajouter un élément et de retirer un élément au sommet de la pile. La fonction ``push`` alloue la mémoire nécessaire avec `malloc(3)`_ tandis que la fonction ``pop`` utilise `free(3)`_ pour libérer la mémoire dès qu'un élément est retiré.
 
 
-.. literalinclude:: /_static/src/C/S3-src/stack.c
+.. literalinclude:: /C/S3-src/stack.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -346,7 +345,7 @@ Lors de la compilation, `gcc(1)`_ affiche le :term:`warning` ``In function ‘du
 
 Ces fonctions peuvent être utilisées pour empiler et dépiler des fractions sur une pile comme dans l'exemple ci-dessous. La fonction ``display`` permet d'afficher sur :term:`stdout` le contenu de la pile.
 
-.. literalinclude:: /_static/src/C/S3-src/stack.c
+.. literalinclude:: /C/S3-src/stack.c
    :encoding: utf-8
    :language: c
    :start-after: ///BBB
@@ -354,7 +353,7 @@ Ces fonctions peuvent être utilisées pour empiler et dépiler des fractions su
 
 Lors de son exécution le programme :download:`/C/S3-src/stack.c` présenté ci-dessus affiche les lignes suivantes sur sa sortie standard.
 
-.. literalinclude:: /_static/src/C/S3-src/stack.out
+.. literalinclude:: /C/S3-src/stack.out
    :encoding: utf-8
    :language: console
 
@@ -376,14 +375,14 @@ Le tas (ou :term:`heap`) joue un rôle très important dans les programmes C. Le
 
 `malloc(3)` est la fonction d'allocation de mémoire la plus fréquemment utilisée [#fothermalloc]_. La librairie standard contient cependant d'autres fonctions permettant d'allouer de la mémoire mais aussi de modifier des allocations antérieures. `calloc(3)`_ est nettement moins utilisée que `malloc(3)`_. Elle a pourtant un avantage majeur par rapport à `malloc(3)`_ puisqu'elle initialise à zéro la zone de mémoire allouée. `malloc(3)`_ se contente d'allouer la zone de mémoire mais n'effectue aucune initialisation. Cela permet à `malloc(3)`_ d'être plus rapide, mais le programmeur ne doit jamais oublier qu'il ne peut pas utiliser `malloc(3)`_ sans initialiser la zone mémoire allouée. Cela peut s'observer en pratique avec le programme ci-dessous. Il alloue une zone mémoire pour ``v1``, l'initialise puis la libère. Ensuite, le programme alloue une nouvelle zone mémoire pour ``v2`` et y retrouve les valeurs qu'il avait stocké pour ``v1`` précédemment. En pratique, n'importe quelle valeur pourrait se trouver dans la zone retournée par `malloc(3)`.
 
-.. literalinclude:: /_static/src/C/S3-src/mallocinit.c
+.. literalinclude:: /C/S3-src/mallocinit.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
 
 L'exécution du programme ci-dessus affiche le résultat suivant sur la sortie standard. Ceci illustre bien que la fonction `malloc(3)`_ n'initialise pas  les zones de mémoire qu'elle alloue.
 
-.. literalinclude:: /_static/src/C/S3-src/mallocinit.out
+.. literalinclude:: /C/S3-src/mallocinit.out
    :encoding: utf-8
    :language: console
 
@@ -395,12 +394,12 @@ Lors de l'exécution du programme, on remarque que la première zone mémoire re
 
 .. [#fpossible] Pour des raisons de performance, le compilateur C ne génère pas de code permettant de vérifier automatiquement qu'un accès via un pointeur pointe vers une zone de mémoire qui est libre. Il est donc parfois possible d'accéder à une zone mémoire qui a été libérée, mais le programme n'a aucune garantie sur la valeur qu'il y trouvera. Ce genre d'accès à des zones mémoires libérées doit bien entendu être complètement proscrit.
 
-.. .. [#ggetrlimit] Sur de nombreuses variantes de Unix, cette limite à la taille du stack dépend du matériel utilisé et peut être configurée par l'administrateur système. Un processus peut connaître la taille maximale de son stack en utilisant l'appel système `getrlimit(2)`_. L'administrateur système peut modifier ces limites via l'appel système `setrlimit(2)`_. La commande ``ulimit`` de `bash(1)`_ permet également de manipuler ces limites.
+.. [#ggetrlimit] Sur de nombreuses variantes de Unix, cette limite à la taille du stack dépend du matériel utilisé et peut être configurée par l'administrateur système. Un processus peut connaître la taille maximale de son stack en utilisant l'appel système `getrlimit(2)`_. L'administrateur système peut modifier ces limites via l'appel système `setrlimit(2)`_. La commande ``ulimit`` de `bash(1)`_ permet également de manipuler ces limites.
 
-.. .. [#fetext] Dans de nombreuses variantes de Unix, il est possible de connaître le sommet du segment :term:`text` d'un processus grâce à la variable :term:`etext`. Cette variable, de type ``char`` est initialisée par le système au chargement du processus. Elle doit être déclarée comme variable de type ``extern char etext`` et son adresse (``&etext``) correspond au sommet du segment text.
+.. [#fetext] Dans de nombreuses variantes de Unix, il est possible de connaître le sommet du segment :term:`text` d'un processus grâce à la variable :term:`etext`. Cette variable, de type ``char`` est initialisée par le système au chargement du processus. Elle doit être déclarée comme variable de type ``extern char etext`` et son adresse (``&etext``) correspond au sommet du segment text.
 
-.. .. [#fvmem] Nous verrons ultérieurement que grâce à l'utilisation de la mémoire virtuelle, il est possible pour un processus d'utiliser des zones de mémoire qui ne sont pas contiguës.
+.. [#fvmem] Nous verrons ultérieurement que grâce à l'utilisation de la mémoire virtuelle, il est possible pour un processus d'utiliser des zones de mémoire qui ne sont pas contiguës.
 
 .. [#fothermalloc] Il existe différentes alternatives à l'utilisation de `malloc(3)`_ pour l'allocation de mémoire comme `Hoard <http://www.hoard.org/>`_ ou `gperftools <http://code.google.com/p/gperftools/>`_
 
-.. .. [#fenvbash] Il possible de lister les définitions actuelles des variables d'environnement via la commande `printenv(1)`_. Les interpréteurs de commande tels que `bash(1)`_ permettent de facilement modifier les valeurs de ces variables. La plupart d'entre elles sont initialisées par le système ou via les fichiers qui sont chargés automatiquement au démarrage de l'interpréteur comme ``/etc/profile`` qui contient les variables fixées par l'administrateur système ou le fichier ``.profile`` du répertoire d'accueil de l'utilisateur qui contient les variables d'environnement propres à cet utilisateur.
+ .. [#fenvbash] Il possible de lister les définitions actuelles des variables d'environnement via la commande `printenv(1)`_. Les interpréteurs de commande tels que `bash(1)`_ permettent de facilement modifier les valeurs de ces variables. La plupart d'entre elles sont initialisées par le système ou via les fichiers qui sont chargés automatiquement au démarrage de l'interpréteur comme ``/etc/profile`` qui contient les variables fixées par l'administrateur système ou le fichier ``.profile`` du répertoire d'accueil de l'utilisateur qui contient les variables d'environnement propres à cet utilisateur.
diff --git a/Theorie/Fichiers/fichiers.rst b/Theorie/Fichiers/fichiers.rst
index 8564b9a7a07e191fa00e897e9b84085e710686e2..fdb676dffc0957aa0475751e84ad263583930794 100644
--- a/Theorie/Fichiers/fichiers.rst
+++ b/Theorie/Fichiers/fichiers.rst
@@ -30,7 +30,7 @@ Les systèmes Unix supportent différents mécanismes d'authentification. Le plu
    username
    inode
    inodes
-   
+
 Lorsqu'un utilisateur se connecte sur un système Unix, il fournit son nom d'utilisateur ou `username`. Ce nom d'utilisateur est une chaîne de caractères qui est facile à mémoriser par l'utilisateur. D'un point de vue implémentation, un système d'exploitation préfère manipuler des nombres plutôt que des chaînes de caractères. Unix associe à chaque utilisateur un identifiant qui est stocké sous la forme d'un nombre entier positif. La table de correspondance entre l'identifiant d'utilisateur et le nom d'utilisateur est le fichier `/etc/passwd`. Ce fichier texte, comme la grande majorité des fichiers de configuration d'un système Unix, comprend pour chaque utilisateur l'information suivante :
 
  - nom d'utilisateur (`username`)
@@ -191,18 +191,18 @@ Il existe plusieurs appels systèmes et fonctions de la librairie standard qui p
 		       char           d_name[256]; /* filename */
 		   };
 
-           
+
 	.. spelling::
 
 	   l'inode
 	   métadonnée
-	   
+
 	Cette structure comprend le numéro de l'inode, c'est-à-dire la métadonnée qui contient les informations relatives au fichier/répertoire, la position de l'entrée ``dirent`` qui suite, la longueur de l'entrée, son type et le nom de l'entrée dans le répertoire. Chaque appel à `readdir(3)`_ retourne un pointeur vers une structure de ce type.
 
 
 	L'extrait de code ci-dessous permet de lister tous les fichiers présents dans le répertoire ``name``.
 
-	.. literalinclude:: /_static/src/Fichiers/src/readdir.c
+	.. literalinclude:: /Fichiers/src/readdir.c
 	   :encoding: utf-8
 	   :language: c
 	   :start-after: ///AAA
@@ -345,7 +345,7 @@ Ces deux appels systèmes prennent trois arguments. Le premier est le `descripte
 
 Il est important de noter que `read(2)`_ et `write(2)`_ permettent de lire et d'écrire des séquences contiguës d'octets. Lorsque l'on écrit ou lit des chaînes de caractères dans lesquels chaque caractère est représenté sous la forme d'un byte, il est possible d'utiliser `read(2)`_ et `write(2)`_ pour lire et écrire d'autres types de données que des octets comme le montre l'exemple ci-dessous.
 
-.. literalinclude:: /_static/src/Fichiers/src/read.c
+.. literalinclude:: /Fichiers/src/read.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -353,7 +353,7 @@ Il est important de noter que `read(2)`_ et `write(2)`_ permettent de lire et d'
 
 Lors de son exécution, ce programme affiche la sortie ci-dessous.
 
-.. literalinclude:: /_static/src/Fichiers/src/read.out
+.. literalinclude:: /Fichiers/src/read.out
    :encoding: utf-8
    :language: console
 
@@ -367,13 +367,13 @@ Le second problème est que les fabricants de processeurs ne se sont pas mis d'a
 
 Pour comprendre ces deux techniques, regardons comment l'entier 16 bits ``0b1111111100000000`` est stocké en mémoire. En :term:`big endian`, le byte ``11111111`` sera stocké à l'adresse `x` et le byte ``00000000`` à l'adresse `x+1`. En :term:`little endian`, c'est le byte ``00000000`` qui est stocké à l'adresse `x` et le byte ``11111111`` qui est stocké à  l'adresse `x+1`. Il en va de même pour les entiers encodés sur 32 bits comme illustré dans les deux figures ci-dessous [#fendianfig]_.
 
-.. figure:: /_static/figures/Fichiers/fig/500px-Big-Endian.png
+.. figure:: /Fichiers/fig/500px-Big-Endian.png
    :align: center
    :scale: 40
 
    Ecriture d'un entier 32 bits en mémoire en `big endian`
 
-.. figure:: /_static/figures/Fichiers/fig/500px-Little-Endian.png
+.. figure:: /Fichiers/fig/500px-Little-Endian.png
    :align: center
    :scale: 40
 
@@ -442,6 +442,3 @@ Cet appel système prend trois arguments. Le premier est le :term:`descripteur d
 .. [#flimit] Il y a une limite maximale au nombre de fichiers qui peuvent être ouverts par un processus. Cette limite peut être récupérée avec l'appel système `getdtablesize(2)`_.
 
 .. [#fendianfig] Source : http://en.wikipedia.org/wiki/Endianness
-
-
-
diff --git a/Theorie/Threads/coordination.rst b/Theorie/Threads/coordination.rst
index d8e15e8087472ab264a0d317ef27efcd10bc684d..6f0ac52d92fe1618b79e7b2b06c630b6057f1f38 100644
--- a/Theorie/Threads/coordination.rst
+++ b/Theorie/Threads/coordination.rst
@@ -110,7 +110,7 @@ Les sémaphores permettent de résoudre de nombreux problèmes classiques. Le pr
 
 Les sémaphores peuvent être utilisés pour d'autres types de synchronisation. Par exemple, considérons une application découpée en threads dans laquelle la fonction ``after`` ne peut jamais être exécutée avant la fin de l'exécution de la fonction ``before``. Ce problème de coordination peut facilement être résolu en utilisant un sémaphore qui est initialisé à la valeur ``0``. La fonction ``after`` doit démarrer par un appel à `sem_wait(3)`_ sur ce sémaphore tandis que la fonction ``before`` doit se terminer par un appel à la fonction `sem_post(3)`_ sur ce sémaphore. De cette façon, si le thread qui exécute la fonction ``after`` est trop rapide, il sera bloqué sur l'appel à `sem_wait(3)`_. S'il arrive à cette fonction après la fin de la fonction ``before`` dans l'autre thread, il pourra passer sans être bloqué. Le programme ci-dessous illustre cette utilisation des sémaphores POSIX.
 
-.. literalinclude:: /_static/src/Threads/S7-src/pthread-sem-before.c
+.. literalinclude:: /Threads/S7-src/pthread-sem-before.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -131,7 +131,7 @@ Le problème des producteurs-consommateurs est un problème extrêmement fréque
 
 Ces deux types de threads communiquent en utilisant un buffer qui a une capacité limitée à `N` places comme illustré dans la figure ci-dessous.
 
-.. figure:: /_static/figures/Threads/figures/figures-S7-001-c.png
+.. figure:: /Threads/figures/figures-S7-001-c.png
    :align: center
    :scale: 80
 
@@ -247,7 +247,7 @@ Il reste cependant quelques concepts qu'il est utile de connaître lorsque l'on
 		movl	%eax, v+4
 		ret
 
-	Le qualificatif ``volatile`` force le compilateur à recharger la variable depuis la mémoire avant chaque utilisation. Ce qualificatif est utile lorsque le contenu stocké à une adresse mémoire peut être modifié par une autre source que le programme lui-même. C'est le cas dans les threads, mais marquer les variables partagées par des threads comme ``volatile`` ne suffit pas. Si ces variables sont modifiées par certains threads, il est nécessaire d'utiliser des :term:`mutex` ou d'autres techniques de coordination pour réguler l'accès en ces variables partagées. En pratique, la documentation du programme devra spécifier quelles variables sont partagées entre les threads et la technique de coordination éventuelle qui est utilisée pour en réguler les accès. L'utilisation du qualificatif ``volatile`` permet de forcer le compilateur à recharger le contenu de la variable depuis la mémoire avant toute utilisation. C'est une règle de bonne pratique qu'il est utile de suivre. Il faut cependant noter que dans l'exemple ci-dessus, l'utilisation du qualificatif ``volatile`` augmente le nombre d'accès à la mémoire et peut donc dans certains cas réduire les performances. 
+	Le qualificatif ``volatile`` force le compilateur à recharger la variable depuis la mémoire avant chaque utilisation. Ce qualificatif est utile lorsque le contenu stocké à une adresse mémoire peut être modifié par une autre source que le programme lui-même. C'est le cas dans les threads, mais marquer les variables partagées par des threads comme ``volatile`` ne suffit pas. Si ces variables sont modifiées par certains threads, il est nécessaire d'utiliser des :term:`mutex` ou d'autres techniques de coordination pour réguler l'accès en ces variables partagées. En pratique, la documentation du programme devra spécifier quelles variables sont partagées entre les threads et la technique de coordination éventuelle qui est utilisée pour en réguler les accès. L'utilisation du qualificatif ``volatile`` permet de forcer le compilateur à recharger le contenu de la variable depuis la mémoire avant toute utilisation. C'est une règle de bonne pratique qu'il est utile de suivre. Il faut cependant noter que dans l'exemple ci-dessus, l'utilisation du qualificatif ``volatile`` augmente le nombre d'accès à la mémoire et peut donc dans certains cas réduire les performances.
 
 Variables spécifiques à un thread
 ---------------------------------
@@ -260,7 +260,7 @@ Une deuxième solution serait d'avoir un tableau global qui contiendrait des poi
 
 Pour résoudre ce problème, deux solutions sont possibles. La première combine une extension au langage C qui est supportée par `gcc(1)`_ avec la librairie threads POSIX. Il s'agit du qualificatif ``__thread`` qui peut être utilisé avant une déclaration de variable. Lorsqu'il est utilisé dans la déclaration d'une variable globale, il indique au compilateur et à la libraire POSIX qu'une copie de cette variable doit être créée pour chaque thread. Cette variable est initialisée au démarrage du thread et est utilisable uniquement à l'intérieur de ce thread. Le programme ci-dessous illustre cette utilisation du qualificatif ``__thread``.
 
-.. literalinclude:: /_static/src/Threads/S7-src/pthread-specific.c
+.. literalinclude:: /Threads/S7-src/pthread-specific.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -268,7 +268,7 @@ Pour résoudre ce problème, deux solutions sont possibles. La première combine
 
 Lors de son exécution, ce programme affiche la sortie suivante sur :term:`stdout`. Cette sortie illustre bien que les variables dont la déclaration est précédée du qualificatif ``__thread`` sont utilisables uniquement à l'intérieur d'un thread.
 
-.. literalinclude:: /_static/src/Threads/S7-src/pthread-specific.out
+.. literalinclude:: /Threads/S7-src/pthread-specific.out
    :encoding: utf-8
    :language: console
 
@@ -285,7 +285,7 @@ Il faut noter que la fonction `pthread_key_create(3posix)`_ associe en pratique
 
 L'exemple ci-dessous illustre l'utilisation de cette API. Elle est nettement plus lourde à utiliser que le qualificatif ``__thread``. Dans ce code, chaque thread démarre par la fonction ``f``. Celle-ci crée une variable spécifique de type ``int`` qui joue le même rôle que la variable ``__thread int count;`` dans l'exemple précédent. La fonction ``g`` qui est appelée sans argument peut accéder à la zone mémoire créée en appelant ``pthread_getspecific(count)``. Elle peut ensuite exécuter ses calculs en utilisant le pointeur ``count_ptr``. Avant de se terminer, la fonction ``f`` libère la zone mémoire qui avait été allouée par `malloc(3)`_. Une alternative à l'appel explicite à `free(3)`_ aurait été de passer ``free`` comme second argument à `pthread_key_create(3posix)`_ lors de la création de la clé ``count``. En effet, ce second argument est la fonction à appeler à la fin du thread pour libérer la mémoire correspondant à cette clé.
 
-.. literalinclude:: /_static/src/Threads/S7-src/pthread-specific2.c
+.. literalinclude:: /Threads/S7-src/pthread-specific2.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -305,7 +305,7 @@ Dans un programme séquentiel, il n'y a qu'un thread d'exécution et de nombreux
 Pour comprendre le problème, il est intéressant de comparer plusieurs implémentations d'une fonction simple. Considérons le problème de déterminer l'élément maximum d'une structure de données contenant des entiers. Si la structure de données est un tableau, une solution simple est de le parcourir entièrement pour déterminer l'élément maximum. C'est ce que fait la fonction ``max_vector`` dans le programme ci-dessous. Dans un programme purement séquentiel dans lequel le tableau peut être modifié de temps en temps, parcourir tout le tableau pour déterminer son maximum n'est pas nécessairement la solution la plus efficace. Une alternative est de mettre à jour la valeur du maximum chaque fois qu'un élément du tableau est modifié. Les fonctions ``max_global`` et ``max_static`` sont deux solutions possibles. Chacune de ces fonctions doit être appelée chaque fois qu'un élément du tableau est modifié. ``max_global`` stocke dans une variable globale la valeur actuelle du maximum du tableau et met à jour cette valeur à chaque appel. La fonction ``max_static`` fait de même en utilisant une variable statique. Ces deux solutions sont équivalentes et elles pourraient très bien être intégrées à une librairie utilisée par de nombreux programmes.
 
 
-.. literalinclude:: /_static/src/Threads/S7-src/reentrant.c
+.. literalinclude:: /Threads/S7-src/reentrant.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
diff --git a/Theorie/Threads/threads.rst b/Theorie/Threads/threads.rst
index c0f15410ac5a86ea6469aa9fcddf5a86d072c120..e2c719c955278ff41eb7a83b566a4f2c0e71f83d 100644
--- a/Theorie/Threads/threads.rst
+++ b/Theorie/Threads/threads.rst
@@ -17,7 +17,7 @@ Les performances des microprocesseurs se sont continuellement améliorées depui
    intel
 
 
-.. figure:: /_static/figures/Threads/figures/534px-Transistor_Count_and_Moore's_Law_-_2011.png
+.. figure:: /Threads/figures/534px-Transistor_Count_and_Moore's_Law_-_2011.png
    :align: center
 
    Evolution du nombre de transistors par microprocesseur
@@ -27,7 +27,7 @@ Cette évolution avait été prédite par Gordon Moore dans les années 1960s [S
 
 Le fonctionnement d'un microprocesseur est régulé par une horloge. Celle-ci rythme la plupart des opérations du processeur et notamment le chargement des instructions depuis la mémoire. Pendant de nombreuses années, les performances des microprocesseurs ont fortement dépendu de leur vitesse d'horloge. Les premiers microprocesseurs avaient des fréquences d'horloge de quelques centaines de :term:`kHz`. A titre d'exemple, le processeur intel 4004 avait une horloge à 740 kHz en 1971. Aujourd'hui, les processeurs rapides dépassent la fréquence de 3 :term:`GHz`. La figure ci-dessous présente l'évolution de la fréquence d'horloge des microprocesseurs depuis les années 1970s [#fperf]_. On remarque une évolution rapide jusqu'aux environs du milieu de la dernière décennie. La barrière des 10 MHz a été franchie à la fin des années 1970s. Les 100 :term:`MHz` ont étés atteints en 1994 et le GHz aux environs de l'an 2000.
 
-.. figure:: /_static/figures/Threads/figures/figures-001-c.png
+.. figure:: /Threads/figures/figures-001-c.png
    :align: center
 
    Evolution de la vitesse d'horloge des microprocesseurs
@@ -45,7 +45,7 @@ Si pendant longtemps la fréquence d'horloge d'un microprocesseur a été une bo
 Une autre façon de mesurer les performances d'un microprocesseur est de comptabiliser le nombre d'instructions qu'il exécute par seconde. On parle en général de Millions d'Instructions par Seconde (ou :term:`MIPS`). Si les premiers microprocesseurs effectuaient moins de 100.000 instructions par seconde, la barrière du MIPS a été franchie en 1979. Mesurées en MIPS, les performances des microprocesseurs ont continué à augmenter durant les dernières années malgré la barrière des 3 GHz comme le montre la figure ci-dessous.
 
 
-.. figure:: /_static/figures/Threads/figures/figures-002-c.png
+.. figure:: /Threads/figures/figures-002-c.png
    :align: center
 
    Evolution des performances des microprocesseurs en MIPS
@@ -67,9 +67,9 @@ Cette progression continue des performances en MIPS a été possible grâce à l
 
 
 La notion de thread d'exécution est très importante dans un système informatique. Elle permet non seulement de comprendre comme un ordinateur équipé d'un seul microprocesseur peut exécuter plusieurs programmes simultanément, mais aussi comment des programmes peuvent profiter des nouveaux processeurs capables d'exécuter plusieurs threads simultanément.
- 
+
 ..
- Pour comprendre cette notion, il est intéressant de revenir à nouveau sur l'exécution d'une fonction en langage assembleur. 
+ Pour comprendre cette notion, il est intéressant de revenir à nouveau sur l'exécution d'une fonction en langage assembleur.
 
 Considérons la fonction ``f`` :
 
@@ -122,7 +122,7 @@ Pour qu'un processeur puisse exécuter cette séquence d'instructions, il faut q
  - à la mémoire contenant les données manipulées par cette séquence d'instruction. Pour rappel, cette mémoire est divisée en plusieurs parties :
 
     - la zone contenant les variables globales
-    - le tas 
+    - le tas
     - la pile
 
 
@@ -194,7 +194,7 @@ Le premier argument de `pthread_join(3)`_ est la structure ``pthread_t`` corresp
 
 L'exemple ci-dessous illustre une utilisation simple des fonctions `pthread_create(3)`_, `pthread_join(3)`_ et `pthread_exit(3)`_.
 
-.. literalinclude:: /_static/src/Threads/S5-src/pthread.c
+.. literalinclude:: /Threads/S5-src/pthread.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -203,7 +203,7 @@ Dans ce programme, la fonction ``main`` lance deux threads. Le premier exécute
 
 Afin d'illustrer la possibilité de passer des arguments à un thread et d'en récupérer la valeur de retour, considérons l'exemple ci-dessous.
 
-.. literalinclude:: /_static/src/Threads/S5-src/pthread-neg.c
+.. literalinclude:: /Threads/S5-src/pthread-neg.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
diff --git a/Theorie/Threads/threads2.rst b/Theorie/Threads/threads2.rst
index a143ca2fcc22c19202f269e4976cce8bd3df8a6a..fc83f36ce7b6d1afb5e0a249659e5d09bd61f273 100644
--- a/Theorie/Threads/threads2.rst
+++ b/Theorie/Threads/threads2.rst
@@ -10,7 +10,7 @@ Communication entre threads
 Lorsque un programme a été décomposé en plusieurs threads, ceux-ci ne sont en général pas complètement indépendants et ils doivent communiquer entre eux. Cette communication entre threads est un problème complexe comme nous allons le voir. Avant d'aborder ce problème, il est utile de revenir à l'organisation d'un processus et de ses threads en mémoire. La figure ci-dessous illustre schématiquement l'organisation de la mémoire après la création d'un thread POSIX.
 
 
-.. figure:: /_static/figures/Threads/S6-fig/figures-001-c.png
+.. figure:: /Threads/S6-fig/figures-001-c.png
    :align: center
    :scale: 80
 
@@ -84,7 +84,7 @@ Malheureusement les difficultés surviennent lorsque deux threads exécutent en
 
  La taille de la pile d'un thread POSIX est l'un des attributs qui peuvent être modifiés lors de l'appel à `pthread_create(3)`_  pour créer un nouveau thread. Cet attribut peut être fixé en utilisant la fonction `pthread_attr_setstackaddr(3posix)`_ comme illustré dans l'exemple ci-dessous [#fpthreadc]_ (où ``thread_first`` est la fonction qui sera appelée à la création du thread). En général, la valeur par défaut choisie par le système suffit, sauf lorsque le programmeur sait qu'un thread devra par exemple allouer un grand tableau auquel il sera le seul à avoir accès. Ce tableau sera alors alloué sur la pile qui devra être suffisamment grande pour le contenir.
 
- .. literalinclude:: /_static/src/Threads/S6-src/pthread.c
+ .. literalinclude:: /Threads/S6-src/pthread.c
     :encoding: utf-8
     :language: c
     :start-after: ///AAA
@@ -95,7 +95,7 @@ Ce problème d'accès concurrent à une zone de mémoire par plusieurs threads e
 
 Le fragment de code ci-dessus présente une autre illustration d'une section critique. Dans cet exemple, la fonction ``main`` (non présentée), créée deux threads. Le premier exécute la fonction ``inc`` qui incrémente la variable ``global``. Le second exécute la fonction ``is_even`` qui teste la valeur de cette variable et compte le nombre de fois qu'elle est paire. Après la terminaison des deux threads, le programme affiche le contenu des variables ``global`` et ``even``.
 
-.. literalinclude:: /_static/src/Threads/S6-src/pthread-test-if.c
+.. literalinclude:: /Threads/S6-src/pthread-test-if.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -172,7 +172,7 @@ Le deuxième type d'événement est l'exécution d'un appel système bloquant. U
 
 Ces interactions entre les threads et le système d'exploitation sont importantes. Pour bien les comprendre, il est utile de noter qu'un thread peut se trouver dans trois états différents du point de vue de son interaction avec le système d'exploitation. Ces trois états sont illustrés dans la figure ci-dessous.
 
-.. figure:: /_static/figures/Threads/S6-fig/figures-003-c.png
+.. figure:: /Threads/S6-fig/figures-003-c.png
    :align: center
    :scale: 80
 
@@ -274,7 +274,7 @@ En C, cela se fait en utilisant les fonctions `pthread_mutex_lock(3posix)`_ et `
 
 L'exemple ci-dessous reprend le programme dans lequel une variable globale est incrémentée par plusieurs threads.
 
-.. literalinclude:: /_static/src/Threads/S6-src/pthread-mutex.c
+.. literalinclude:: /Threads/S6-src/pthread-mutex.c
    :encoding: utf-8
    :language: c
    :start-after: ///AAA
@@ -303,9 +303,9 @@ Pour montrer que la propriété de vivacité est bien respectée, il faut montre
 
 .. rubric:: Footnotes
 
-.. [#fexemple] Le programme complet est accessible via :download:`/_static/src/Threads/S5-src/pthread-test.c`
+.. [#fexemple] Le programme complet est accessible via :download:`/Threads/S5-src/pthread-test.c`
 
-.. [#fpthreadc] Le programme complet est accessible via :download:`/_static/src/Threads/S6-src/pthread.c`
+.. [#fpthreadc] Le programme complet est accessible via :download:`/Threads/S6-src/pthread.c`
 
 .. .. [#fframes] Il existe différents standards pour le nombre d'images par seconde en cinéma et en télévision. Les plus courants sont 24, 25 et 30 images par seconde. Voir http://en.wikipedia.org/wiki/Frame_rate
 
@@ -317,4 +317,4 @@ Pour montrer que la propriété de vivacité est bien respectée, il faut montre
 
 .. [#fstaticinit] Linux supporte également la macro ``PTHREAD_MUTEX_INITIALIZER`` qui permet d'initialiser directement un ``pthread_mutex_t`` déclaré comme variable globale. Dans cet exemple, la déclaration aurait été : ``pthread_mutex_t global_mutex=PTHREAD_MUTEX_INITIALIZER;`` et l'appel à `pthread_mutex_init(3posix)`_ aurait été inutile. Comme il s'agit d'une extension spécifique à Linux, il est préférable de ne pas l'utiliser pour garantir la portabilité du code.
 
-.. [#fphilo] Le programme complet est :download:`/_static/src/Threads/S6-src/pthread-philo.c`
+.. [#fphilo] Le programme complet est :download:`/Threads/S6-src/pthread-philo.c`