diff --git a/Makefile b/Makefile index fa6e8f44c6ff76b09bd90f002ad8ace5a638e381..2a369d840ae922faa3768b19d771387da4e8e6e2 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,9 @@ REVEALOPTIONS += --self-contained REVEALOPTIONS += -V revealjs-url=./reveal.js REVEALOPTIONS += -V theme=white -all: base_4.pdf base_3.pdf base_2.pdf base_1.pdf intro.pdf command_line.pdf index.html +all: base_5.pdf base_4.pdf base_3.pdf base_2.pdf base_1.pdf intro.pdf command_line.pdf index.html -all_html: intro.html base_1.html base_2.html base_3.html base_4.html command_line.html +all_html: intro.html base_1.html base_2.html base_3.html base_4.html base_5.html command_line.html intro.pdf: intro.md metadata.yaml pandoc $(PDFOPTIONS) -o $@ $^ @@ -49,6 +49,12 @@ base_4.pdf: base_4.md metadata.yaml base_4.html: base_4.md metadata.yaml pandoc $(REVEALOPTIONS) -o $@ $^ +base_5.pdf: base_5.md metadata.yaml + pandoc $(PDFOPTIONS) -o $@ $^ + +base_5.html: base_5.md metadata.yaml + pandoc $(REVEALOPTIONS) -o $@ $^ + command_line.pdf: command_line.md metadata.yaml pandoc $(PDFOPTIONS) -o $@ $^ diff --git a/base_5.md b/base_5.md index dbea1fe031c68f8735f1515b50776ec638ec10e9..52c88bd8e1497d94efab5dc3db86ca6da7f23e83 100644 --- a/base_5.md +++ b/base_5.md @@ -2,37 +2,11 @@ % Inspirés des slides de F. Glück % 14 octobre 2020 -# Représentation des variables en mémoire (1/2) - -## La mémoire - -* La mémoire est: - - ... un ensemble de bits, - - ... accessible via des adresses, - - +------+----------+----------+------+----------+------+------+ - | bits | 00110101 | 10010000 | .... | 00110011 | .... | .... | - +======+==========+==========+======+==========+======+======+ - | addr | 2000 | 2001 | .... | 4000 | .... | .... | - +------+----------+----------+------+----------+------+------+ - - - ... gérée par le système d'exploitation. - - ... séparée en deux parties: **la pile** et **le tas**. - -## Une variable - -* Une variable, `type a = valeur`{.C}, possède: - - un type (`char`{.C}, `int`{.C}, ...), - - un contenu (une séquence de bits qui encode `valeur`{.C}), - - une adresse mémoire (accessible via `&a`{.C}), - - une portée. - - -# Représentation des variables en mémoire (2/2) +# Rappel: représentation des variables en mémoire {#fig:memory width=100%} -# Les pointeurs (1/3) +# Rappel: Les pointeurs (1/3) - Un pointeur est une adresse mémoire. @@ -52,11 +26,11 @@ - `NULL`{.C} (ou `0`{.C}) est la seule adresse **toujours** invalide. -# Les pointeurs (2/3) +# Rappel: Les pointeurs (2/3) {#fig:memory width=100%} -# Les pointeurs (3/3) +# Rappel: Les pointeurs (3/3) - Permettent d'accéder à une valeur avec une indirection. @@ -128,7 +102,7 @@ ``` - Pour chaque `malloc()`{.C} doit correspondre exactement un `free()`{.C}. - Si la mémoire n'est pas libérée: **fuite mémoire** (l'ordinateur plante quand il y a plus de mémoire). -- Si la mémoire est **libérée deux** fois: seg fault. +- Si la mémoire est **libérée deux** fois: *seg. fault*. - Pour éviter les mauvaises surprises mettre `ptr`{.C} à `NULL`{.C}. # Allocation dynamique de mémoire (4/8) @@ -183,7 +157,6 @@ ## Pointeur de pointeur - {#fig:compilation height=100%} # Allocation dynamique de mémoire (8/8) @@ -200,200 +173,6 @@ - Ceci est une matrice (un tableau de tableau). -# Prototypes de fonctions (1/N) - -## Principes généraux de programmation - -- Beaucoup de fonctionnalités dans un code $\Rightarrow$ Modularisation. -- Modularisation du code $\Rightarrow$ écriture de fonctions. -- Beaucoup de fonctions $\Rightarrow$ regrouper les fonctions dans des fichiers séparés. - -## Mais pourquoi? - -- Lisibilité. -- Raisonnement sur le code. -- Débogage. - -## Exemple - -- Libraire `stdio.h`: `printf()`{.C}, `scanf()`{.C}, ... - -# Prototypes de fonctions (2/N) - -- Prototypes de fonctions nécessaires quand: - - 1. Utilisation de fonctions dans des fichiers séparés. - 2. Utilisation de librairies. -- Un prototype indique au compilateur la signature d'une fonction. -- On met les prototypes des fonctions **publiques** dans des fichiers *headers*, extension `.h`. -- Les *implémentations* des fonctions vont dans des fichier `.c`. - -# Prototypes de fonctions (3/N) - -## Fichier header - -- Porte l'extension `.h` -- Contient: - - définitions des types - - prototypes de fonctions - - macros - - directives préprocesseur (cf. plus loin) -- Utilisé pour décrire **l'interface** d'une librairie ou d'un module. -- Un fichier `C` (extension `.c`) utilise un header en *l'important* avec la directive `#include`{.C}: - - ```C - #include <stdio.h> // libraire dans LD_LIBRARY_PATH - #include "chemin/du/prototypes.h"// chemin explicite - ``` - -# Génération d'un exécutable (1/N) - -## Un seul fichier source - -{#fig:compilation width=100%} - -# Génération d'un exécutable (2/N) - -## Un seul fichier source - -```bash -gcc proc.c -o prog -``` - -1. **Précompilation: ** `gcc` appelle `cpp`, le préprocesseur qui effectue de la substitution de texte (`#define`, `#include`, macros, ...) et génère le code `C` à compiler, portant l'extension `.i` (`prog.i`). -2. **Compilation assembleur: ** `gcc` compile le code C en code assembleur, portant l'extension `.s` (`prog.s`). -3. **Compilation code objet: ** `gcc` appelle `as`, l'assembleur, qui compile le code assembleur en code machine (code objet) portant l'extension `.o` (`prog.o`). -4. **Édition des liens: ** `gcc` appelle `ld`, l'éditeur de liens, qui lie le code objet avec les librairies et d'autres codes objet pour produire l'exécutable final (`prog`). - -Les différents codes intermédiaires sont effacés. - -# Génération d'un exécutable (3/N) - -## Plusieurs fichiers sources - -{#fig:compilation_plusieurs width=100%} - -# Génération d'un exécutable (4/N) - -::: Main - -## `main.c` - -```C -#include <stdio.h> -#include "sum.h" -int main() { - int tab[] = {1, 2, 3, 4}; - printf("sum: %d\n", sum(tab, 4)); - return 0; -} -``` -::: - -:::::::::::::: {.columns} - -::: {.column width="45%"} - -## `sum.h` - -```C -#ifndef _SUM_H_ -#define _SUM_H_ - -int sum(int tab[], int n); - -#endif -``` -::: -::: {.column width="55%"} - -## `sum.c` - -```C -#include "sum.h" -int sum(int tab[], int n) { - int s = 0; - for (int i = 0; i < n; i++) { - s += tab[i]; - } - return s; -} -``` -::: - -:::::::::::::: - - -# Génération d'un exécutable (4/N) - -La compilation séparée se fait en plusieurs étapes. - -## Compilation séparée - -1. Générer séparément les fichiers `.o` avec l'option `-c`. -2. Éditer les liens avec l'option `-o` pour générer l'exécutable. - -## Exemple - -- Création des fichiers objets, `main.o` et `sum.o` - - ```bash - $ gcc -Wall -Wextra -std=c11 -c main.c - $ gcc -Wall -Wextra -std=c11 -c sum.c - ``` -- Édition des liens - - ```bash - $ gcc main.o sum.o -o prog - ``` - -# Préprocesseur (1/N) - -## Généralités - -- Première étape de la chaîne de compilation. -- Géré automatiquement par `gcc` ou `clang`. -- Lit et interprète certaines directives: - 1. Les commentaires (`//`{.C} et `/* ... */`{.C}). - 2. Les commandes commençant par `#`{.C}. -- Le préprocesseur ne compile rien, mais subtitue uniquement du texte. - -## La directive `define`{.C} - -- Permet de définir un symbole: - - ```C - #define PI 3.14159 - #define _SUM_H_ - ``` -- Permet de définir une macro. - - ```C - #define NOM_MACRO(arg1, arg2, ...) [code] - ``` - -# Préprocesseur (2/N) - -## La directive `include`{.C} - -- Permet d'inclure un fichier. -- Le contenu du fichier est ajouté à l'endroit du `#include`{.C}. -- Inclusion de fichiers "globaux" ou "locaux" - - ```C - #include <file.h> // LD_LIBRARY_PATH - #include "other_file.h" // local path - ``` -- Les inclusions multiples peuvent poser problème: définitions multiples. Les headers commencent par: - - ```C - #ifndef _VAR_ - #define _VAR_ - /* - commentaires - */ - #endif - ```