--- jupytext: text_representation: extension: .md format_name: myst format_version: 0.13 kernelspec: display_name: C++17 language: C++17 name: xcpp17 rise: auto_select: first autolaunch: false centered: false controls: false enable_chalkboard: true height: 100% margin: 0 maxScale: 1 minScale: 1 scroll: true slideNumber: true start_slideshow_at: selected transition: none width: 90% --- # Cycle de vie d'un programme ## Revenons à la recette de la mousse au chocolat :::{admonition} Ingrédients :icon: false 250 g de chocolat, 125 g de beurre, 6 œufs, 50 g de sucre, café ::: :::{admonition} Étapes :icon: false - Faire fondre le chocolat avec deux cuillères d'eau - Ajouter le beurre, laisser refroidir puis ajouter les jaunes - Ajouter le sucre et comme parfum un peu de café - Battre les blancs jusqu'à former une neige uniforme - Ajouter au mélange ::: +++ {"slideshow": {"slide_type": "fragment"}} **Est-ce bien un programme ?** +++ {"slideshow": {"slide_type": "fragment"}} Pour répondre à cette question, revenons à la définition : :::{prf:definition} **Programme** (rappel) Séquence d'**instructions** qui spécifie, étape par étape, les opérations à effectuer pour obtenir, à partir des **entrées**, un résultat, la **sortie**. ::: +++ {"slideshow": {"slide_type": "slide"}} ### Oui, mais c'est quoi une instruction ? Prenons quelques candidats : - « Lever le bras de 10 cm, tendre la main vers la gauche, prendre la casserole rouge, ... » Trop détaillé, illisible, non portable +++ {"slideshow": {"slide_type": "fragment"}} - « Préparer une mousse au chocolat » Trop abstrait et non informatif +++ {"slideshow": {"slide_type": "fragment"}} - « avec deux cuillères d'eau » Ambigu : c'est combien une cuillère ? +++ {"slideshow": {"slide_type": "fragment"}} - « Zwei Eiweiß in Eischnee schlagen » Dans quelle langue ? +++ {"slideshow": {"slide_type": "fragment"}} Cela nous amène naturellement à la question suivante : **Quelles sont les instructions compréhensibles par un ordinateur ?** +++ {"slideshow": {"slide_type": "slide"}} ## Au commencement était l'assembleur :::{prf:definition} Assembleur L'***assembleur*** est le langage que comprend directement l'ordinateur. Chaque instruction correspond à une opération élémentaire que peut effectuer le processeur. ::: +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} :::{prf:example} ``` nasm mov -0x1c(%rbp), %edx mov -0x1c(%rbp), %eax imul %edx, %eax mov %eax, -0x18(%rbp) mov -0x18(%rbp), %eax imul -0x18(%rbp), %eax mov %eax, -0x14(%rbp) ``` ::: +++ {"slideshow": {"slide_type": "fragment"}} Voyons cet exemple de plus près. :::{exercise} Exécuter ce fragment d'*assembleur* en suivant les indications suivantes : - `%eax, %edx` sont des registres (cases mémoire du processeur) l'analogue des variables - `-0x14(%rbp), ..., -0x1c(%rbp)` : autres cases mémoire - `mov a, b` : copier le contenu de la case a dans la case b - `imul a, b` : multiplier le contenu de a par celui de b et mettre le résultat dans b - Initialiser le contenu de la case `%-0x1c(%rbp)` à $3$ ::: +++ {"slideshow": {"slide_type": "fragment"}} Vous avez réussi ? Bravo, vous pourrez dire que vous avez fait de l'assembleur ! Comme vous le constatez, rien de magique. Mais on est bien content de ne pas avoir à programmer tout le temps en assembleur. +++ {"slideshow": {"slide_type": "slide"}} ## Cycle de vie d'un programme +++ {"slideshow": {"slide_type": "fragment"}} ### Motivation **Ce que je veux :** « Calculer la puissance quatrième d'un nombre » +++ {"slideshow": {"slide_type": "fragment"}} **Ce que l'ordinateur sait faire :** ``` nasm ... mov -0x1c(%rbp), %edx mov -0x1c(%rbp), %eax imul %edx, %eax mov %eax, -0x18(%rbp) mov -0x18(%rbp), %eax imul -0x18(%rbp), %eax mov %eax, -0x14(%rbp) ... ``` +++ {"slideshow": {"slide_type": "fragment"}} **Passer de l'un à l'autre ne va pas se faire tout seul**. Il va falloir un peu de méthode. C'est le **cycle de vie d'un programme**. +++ {"slideshow": {"slide_type": "slide"}} ### Cycle de vie d'un programme Nous allons passer en revue les différentes étapes du cycle de vie d'un programme, partant d'un problème à résoudre jusqu'à un programme fonctionnel. +++ {"slideshow": {"slide_type": "fragment"}} :::{admonition} Problème « Calculer la puissance quatrième d'un nombre » ::: +++ {"slideshow": {"slide_type": "fragment"}} :::{admonition} Formalisation - Spécification des **entrées** et des **sorties** - Scénario d'utilisation : « l'utilisateur saisit au clavier un nombre entier $x$ ; l'ordinateur affiche la valeur de $x^4$ à l'écran » ::: +++ {"slideshow": {"slide_type": "fragment"}} :::{admonition} Recherche d'un algorithme - Comment on résout le problème ? - Quel **traitement** appliquer à l'entrée pour obtenir la sortie désirée ? ::: +++ {"slideshow": {"slide_type": "fragment"}} On note que $x^4=x * x * x * x = (x^2)^2$ +++ {"slideshow": {"slide_type": "fragment"}} Cela nous donne un **algorithme** : - calculer $x*x$ - prendre le résultat et faire de même +++ {"slideshow": {"slide_type": "slide"}} ### Digression : La notion d'algorithme :::{prf:definition} Algorithme - Description formelle d'un procédé de traitement qui permet, à partir d'un ensemble d'informations initiales, d'obtenir des informations déduites - Succession finie et non ambiguë d'opérations clairement posées ::: +++ {"slideshow": {"slide_type": "fragment"}} Quelle différence entre un **algorithme** et un **programme** ? +++ {"slideshow": {"slide_type": "fragment"}} Un algorithme: - doit toujours se terminer ! - est conçu pour communiquer entre humains - est un concept indépendant du langage dans lequel il est écrit +++ {"slideshow": {"slide_type": "slide"}} ### Cycle de vie d'un programme : implantation **Et maintenant ?** L'algorithme s'adresse à un humain On veut l'expliquer à un ordinateur ... ... qui est stupide ; et ne comprend pas le français ! +++ {"slideshow": {"slide_type": "fragment"}} **Écriture d'un programme :** En assembleur ??? - Trop détaillé - Non portable - Illisible pour l'humain ! +++ {"slideshow": {"slide_type": "fragment"}} **En C++ :** Entrée : ```{code-cell} int x = 3; ``` Traitement : ```{code-cell} int xCarre = x * x; int xPuissanceQuatre = xCarre * xCarre; ``` Sortie : ```{code-cell} xPuissanceQuatre ``` +++ {"slideshow": {"slide_type": "slide"}} #### Niveaux de langages de programmation +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} **Langage machine (binaire) :** Un programme y est directement compréhensible par la machine +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} **Langage d'assemblage (ou assembleur) :** Un programme y est traduisible mot-à-mot en langage machine +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} **Langage de programmation :** En général, un programme doit être **transformé** pour être compris par la machine +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} Comment faire cette transformation ? À la main ? +++ {"slideshow": {"slide_type": "slide"}} ### Transformer en binaire +++ {"slideshow": {"slide_type": "fragment"}} #### Les interpréteurs **Exemple : interpréteur C++ dans Jupyter (xeus-cling) :** +++ {"slideshow": {"slide_type": "fragment"}} **Chaîne de production :** 1. L'utilisateur saisit une **instruction source** 2. L'**interpréteur** la convertit en succession d'**instructions machine** 3. Le processeur exécute les instructions +++ {"slideshow": {"slide_type": "fragment"}} Exemples de langages de programmation avec un interpréteur : Basic, Javascript, LISP, Perl, Python, C++, ... +++ {"slideshow": {"slide_type": "slide"}} #### Les compilateurs **Exemple : compilation en C++ :** - Programme source : `puissance-quatre.cpp` - Compilation : `clang++ puissance-quatre.cpp -o puissance-quatre` - Programme objet (ou binaire) : `puissance-quatre` - Exécution : `./puissance-quatre` - Fabrication de l'assembleur : `clang++ -S puissance-quatre.cpp` - Programme en assembleur : `puissance-quatre.s` +++ {"slideshow": {"slide_type": "fragment"}} **Exemple :** Observez le contenu de `puissance-quatre.s`, et retrouvez les instructions assembleur étudiées plus haut. +++ {"slideshow": {"slide_type": "fragment"}} **Chaîne de production :** 1. L'utilisateur saisit un **programme source** 2. Le **compilateur** convertit tout le programme en un **programme objet** (écrit en binaire) 3. L'utilisateur lance l'exécution du programme objet Exemples de langages de programmation avec un compilateur : ADA, C, C++, FORTRAN, Java, Pascal, ... +++ {"slideshow": {"slide_type": "slide"}} ### Exécution et mise au point :::{admonition} Exécuter le programme - Autant de fois que l'on veut ! ::: +++ {"slideshow": {"slide_type": "fragment"}} :::{admonition} Tester que le programme fonctionne - En n'oubliant pas les cas particuliers !!! ::: +++ {"slideshow": {"slide_type": "fragment"}} :::{admonition} Mise au point - Correction d'erreurs - Optimisation du programme (consommation de ressources: temps, mémoire, énergie, ...) - Optimisation de l'algorithme - Amélioration du programme (lisibilité, généralisation) ::: +++ {"slideshow": {"slide_type": "fragment"}} À chaque fois, on reboucle sur l'étape de compilation, voire de conception, d'où le terme de **cycle de vie**. +++ {"slideshow": {"slide_type": "slide"}} ## Cycle de vie d'un programme : résumé Passer d'un **problème à résoudre** que l'on a en tête à un **programme exécutable par l'ordinateur** est un grand saut. Heureusement, on peut s'appuyer sur un peu de +++ {"slideshow": {"slide_type": "fragment"}} :::{admonition} Méthodologie 1. Énoncé du problème 2. Formalisation (quel est le problème précisément ?) 3. Recherche d'un algorithme (comment résoudre le problème ?) 4. Programmation (implantation) 5. Interprétation / Compilation 6. Exécution 7. Mise au point (test, débogage, optimisation, diffusion) ::: +++ {"slideshow": {"slide_type": "skip"}} ## Suite Maintenant que nous avons clarifié la notion de compilation, vous êtes prêts pour la [compilation séparée](cours-modularite.md).