--- 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 **Ingrédients :** 250 g de chocolat, 125 g de beurre, 6 œufs, 50 g de sucre, café **Étapes :** - 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 : **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 » L'assembleur est le langage que comprend directement l'ordinateur. Chaque instruction correspond à une opération élémentaire que peut effectuer le processeur : ``` 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) ``` Voyons cet exemple de plus près. +++ {"slideshow": {"slide_type": "fragment"}} **Exercice :** 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 4 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"}} #### Problème « Calculer la puissance 4 d'un nombre » +++ {"slideshow": {"slide_type": "fragment"}} #### Formalisation Spécification des **entrées** et des **sorties** Scénario d'utilisation : « l'utilisateur rentre au clavier un nombre entier $x$ ; l'ordinateur affiche en retour la valeur de $x^4$ à l'écran » +++ {"slideshow": {"slide_type": "fragment"}} #### 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$ 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 **Définition : 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": "slide"}} **Langage machine (binaire) :** Un programme y est directement compréhensible par la machine +++ {"slideshow": {"slide_type": "slide"}} **Langage d'assemblage (ou assembleur) :** Un programme y est traduisible mot-à-mot en langage machine +++ {"slideshow": {"slide_type": "slide"}} **Langage de programmation :** En général, un programme doit être **transformé** pour être compris par la machine +++ {"slideshow": {"slide_type": "slide"}} 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 : `g++ puissance-quatre.cpp -o puissance-quatre` - Programme objet (ou binaire) : `puissance-quatre` - Exécution : `./puissance-quatre` - Fabrication de l'assembleur : `g++ -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 **Exécuter le programme :** - Autant de fois que l'on veut ! +++ {"slideshow": {"slide_type": "fragment"}} **Tester que le programme fonctionne :** - En n'oubliant pas les cas particuliers !!! +++ {"slideshow": {"slide_type": "fragment"}} **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"}} **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).