Skip to content
Snippets Groups Projects
Verified Commit f995e8c0 authored by orestis.malaspin's avatar orestis.malaspin
Browse files
parents ef619340 a5ed5915
No related branches found
No related tags found
No related merge requests found
Showing
with 9052 additions and 2 deletions
---
title: "Allocation dynamique de mémoire"
date: "2023-12-07"
---
# Allocation dynamique de mémoire (1/7)
- La fonction `malloc`{.C} permet d'allouer dynamiquement (pendant l'exécution du programme) une zone de mémoire contiguë.
```C
#include <stdlib.h>
void *malloc(size_t size);
```
- `size`{.C} est la taille de la zone mémoire **en octets**.
- Retourne un pointeur sur la zone mémoire ou `NULL`{.C} en cas d'échec: **toujours vérifier** que la valeur retournée est `!= NULL`{.C}.
- Le *type* du retour est `void *`{.C} (un pointeur de type quelconque).
# Allocation dynamique de mémoire (2/7)
- On peut allouer et initialiser une `fraction_t`{.C}:
```C
fraction_t *frac = malloc(sizeof(fraction_t));
frac->num = 1;
frac->denom = -1;
```
- La zone mémoire **n'est pas** initialisée.
- Désallouer la mémoire explicitement, sinon **fuites mémoires**.
- Il faut connaître la **taille** des données à allouer.
![La représentation mémoire de `fraction_t` et fuites.](figs/pointer_struct_ok.svg){width=100%}
# Allocation dynamique de mémoire (3/7)
- La fonction `free()`{.C} permet de libérer une zone préalablement allouée avec `malloc()`{.C}.
```C
#include <stdlib.h>
void free(void *ptr);
```
- A 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*.
- Pour éviter les mauvaises surprises mettre `ptr`{.C} à `NULL`{.C} après
libération.
# Allocation dynamique de mémoire (4/7)
## Tableaux dynamiques
- Pour allouer un espace mémoire de 50 entiers: un tableau
```C
int *p = malloc(50 * sizeof(int));
for (int i = 0; i < 50; ++i) {
p[i] = 0;
}
```
## Arithmétique de pointeurs
- Parcourir la mémoire différemment qu'avec l'indexation
```C
int *p = malloc(50 * sizeof(int));
// initialize somehow
int a = p[7];
int b = *(p + 7); // on avance de 7 "int"
p[0] == *p; // le pointeur est le premier élément
```
# Allocation dynamique de mémoire (5/7)
## Arithmétique de pointeurs
![L'arithmétique des pointeurs.](figs/pointer_arithmetics.svg){width=100%}
## Quelle est la complexité de l'accès à une case d'un tableau?
. . .
$$
\mathcal{O}(1).
$$
# Allocation dynamique de mémoire (6/7)
## Pointeur de pointeur
- Tout comme une valeur a une adresse, un pointeur a lui-même une adresse:
```C
int a = 2;
int *b = &a;
int **c = &b;
```
- En effet, un pointeur est aussi une variable (une variable qui contient une adresse mémoire).
- Chaque `*`{.C} rajoute une indirection.
# Allocation dynamique de mémoire (6/7)
## Pointeur de pointeur
![Les références de pointeurs.](figs/double_pointeur.svg){height=100%}
# Allocation dynamique de mémoire (7/7)
- Avec `malloc()`, on peut allouer dynamiquement des tableaux de pointeurs:
```C
int **p = malloc(50 * sizeof(int*));
for (int i = 0; i < 50; ++i) {
p[i] = malloc(70 * sizeof(int));
}
int a = p[5][8]; // on indexe dans chaque dimension
```
- Ceci est une matrice (un tableau de tableaux).
# Tableau dynamique en argument d'une fonction
## Implémenter la fonction ci-dessous
```C
int32_t *p = malloc(50 * sizeof(*p));
initialize_to(p, 50, -1); // initialise un tableau à -1
free(p); // ne pas oublier
```
. . .
```C
void initialize_to(int32_t *p, size_t size, int32_t val) {
for (size_t i = 0; i < size; ++i) {
p[i] = val;
}
}
```
# Tableau dynamique retourné d'une fonction
## Implémenter la fonction ci-dessous
```C
// alloue un tableau de taille 50 et l'initialise à -1
int32_t *p = initialize_to(50, -1);
free(p); // ne pas oublier
```
. . .
```C
int32_t *initialize_to(size_t size, int32_t val) {
int32_t *p = malloc(size * sizeof(*p));
for (size_t i = 0; i < size; ++i) {
p[i] = val;
}
return p;
}
```
## Pourquoi on peut retourner un tableau dynamique et pas un statique?
. . .
* Le tableau est alloué sur le **tas** et non sur la **pile**.
* La mémoire est gérée manuellement sur le tas, automatiquement sur la pile.
# Les *sanitizers*
Problèmes mémoire courants:
* Dépassement de capacité de tableaux.
* Utilisation de mémoire non allouée.
* Fuites mémoire.
* Double libération.
Outils pour leur détection:
* Valgrind (outil externe).
* Sanitizers (ajouts de marqueurs à la compilation).
Ici on utilise les sanitizers (modification de la ligne de compilation, modifiez donc vos *Makefile*):
```bash
gcc -o main main.c -g -fsanitize=address -fsanitize=leak
```
**Attention:** Il faut également faire l'édition des liens avec les sanitizers.
# Questions
## Que fait le code suivant?
```C
int *p = malloc(50 * sizeof(int));
p[10] = 1;
```
. . .
* On alloue de la place pour 50 entiers.
* On initialise le 11ème élément du tableau à 1.
* Les autres éléments sont non-initialisés.
# Questions
## Que fait le code suivant?
```C
float *p = malloc(50);
p[20] = 1.3;
```
. . .
* On déclare un pointeur de floats de taille 50 octets.
* Mais il ne peut contenir que `50 / 4` floats (un float est composé de 32 bits).
* On dépasse la capacité de la mémoire allouée: comportement indéfini.
# Questions
* Soit le code suivant
```C
int *p = malloc(50 * sizeof(int));
for (int i = 0; i < 50; ++i) {
p[i] = 0;
}
```
* Le réécrire en utilisant uniquement l'arithmétique de pointeurs.
. . .
```C
int *p = malloc(50 * sizeof(int));
for (int i = 0; i < 50; ++i) {
*(p+i) = 0;
}
```
# Questions
## Que valent les expressions suivantes?
```C
in32_t *p = malloc(50 * sizeof(int32_t));
sizeof(p);
sizeof(*p);
(p + 20);
*(p + 20);
p[-1];
p[50];
7[p];
```
---
title: "Compilation séparée et Makefile"
date: "2023-11-02"
---
# Prototypes de fonctions (1/3)
```C
// Prototype, pas d'implémentation, juste la doc
int sum(int size, int tab[size]);
```
## 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/3)
- 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/3)
## 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> // dans LD_LIBRARY_PATH
#include "chemin/du/prototypes.h" // explicite
```
# Génération d'un exécutable (1/5)
## Un seul fichier source
![Étapes de génération.](figs/compilation.svg){width=100%}
# Génération d'un exécutable (2/5)
\footnotesize
```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 automatiquement.
# Génération d'un exécutable (3/5)
## Plusieurs fichiers sources
![Étapes de génération, plusieurs fichiers.](figs/compilation_plusieurs.svg){width=100%}
# Génération d'un exécutable (4/5)
\footnotesize
::: 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 (5/5)
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/2)
\footnotesize
## 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/2)
## 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
```
- Inclusions multiples peuvent poser problème: définitions multiples. Les headers commencent par:
```C
#ifndef _VAR_
#define _VAR_
/* commentaires */
#endif
```
# Introduction à `make`
## A quoi ça sert?
- Automatiser le processus de conversion d'un type de fichier à un autre, en *gérant les dépendances*.
- Effectue la conversion des fichiers qui ont changé uniquement.
- Utilisé pour la compilation:
- Création du code objet à partir des sources.
- Création de l'exécutable à partir du code objet.
- Tout "gros" projet utilise `make` (pas uniquement en `C`).
# Utilisation de `make`
\footnotesize
Le programme `make` exécutera la série d'instruction se trouvant dans un `Makefile` (ou `makefile` ou `GNUmakefile`).
## Le `Makefile`
- Contient une liste de *règles* et *dépendances*.
- Règles et dépendances construisent des *cibles*.
- Ici utilisé pour compiler une série de fichiers sources
```
$ gcc -c example.c # + plein d'options..
$ gcc -o example exemple.o # + plein d'options
```
:::::::::::::: {.columns}
::: {.column width="55%"}
## `Makefile`
```bash
example: example.o
gcc -o example example.o
exmaple.o: exmaple.c example.h
gcc -c example.c
```
:::
::: {.column width="45%"}
## Terminal
```bash
$ make
gcc -c example.c
gcc -o example example.o
```
:::
::::::::::::::
# Syntaxe d'un `Makefile` (1/4)
![Un exemple simple de `Makefile`.](figs/ex_makefile.svg){width=100%}
# Syntaxe d'un `Makefile` (2/4)
![La cible.](figs/ex_makefile_cible.svg){width=100%}
# Syntaxe d'un `Makefile` (3/4)
![Les dépendances.](figs/ex_makefile_dep.svg){width=100%}
# Syntaxe d'un `Makefile` (4/4)
![La règle.](figs/ex_makefile_regle.svg){width=100%}
# Principe de fonctionnement
1. `make` cherche le fichier `Makefile`, `makefile` ou `GNUmakefile` dans le répertoire courant.
2. Par défaut exécute la première cible, ou celle donnée en argument.
3. Décide si une cible doit être régénérée en comparant la date de modification (on recompile que ce qui a été modifié).
4. Regarde si les dépendances doivent être régénérées:
- Oui: prend la première dépendance comme cible et recommence à 3.
- Non: exécute la règle.
`make` a un comportement **récursif**.
# Exemple avancé
:::::::::::::: {.columns}
::: {.column width="55%"}
## `Makefile`
```bash
hello: hello.o main.o
gcc hello.o main.o -o hello
hello.o: hello.c hello.h
gcc -Wall -Wextra -c hello.c
main.o: main.c
gcc -Wall -Wextra -c main.c
clean:
rm -f *.o hello
rebuild: clean hello
```
:::
::: {.column width="45%"}
## Un graph complexe
![`Makefile` complexe.](figs/complex_makefile.svg){width=100%}
:::
::::::::::::::
<!-- # Factorisation
:::::::::::::: {.columns}
::: {.column width="55%"}
## Ancien `Makefile`
```bash
hello: hello.o main.o
gcc hello.o main.o -o hello
hello.o: hello.c hello.h
gcc -Wall -Wextra -c hello.c
main.o: main.c
gcc -Wall -Wextra -c main.c
clean:
rm -f *.o hello
rebuild: clean hello
```
:::
::: {.column width="45%"}
## Nouveau `Makefile`
```bash
CC=gcc -Wall -Wextra
hello: hello.o main.o
$(CC) $^ -o $@
hello.o: hello.c hello.h
$(CC) -c $<
main.o: main.c
$(CC) -c $<
clean:
rm -f *.o hello
rebuild: clean hello
```
:::
::::::::::::::
# Variables
\footnotesize
## Variables utilisateur
- Déclaration
```bash
id = valeur
id = valeur1 valeur2 valeur3
```
- Utilisation
```bash
$(id)
```
- Déclaration à la ligne de commande
```bash
make CFLAGS="-O3 -Wall"
```
## Variables internes
- `$@` : la cible
- `$^` : la liste des dépendances
- `$<` : la première dépendance
- `$*` : le nom de la cible sans extension
-->
---
title: "Précisions pour l'examen"
date: "2023-11-16"
---
# Administration
- L'examen se déroule sur `nexus`.
- L'examen dure au plus 4h (il est prévu pour 3 exceptions jusqu'à 4).
- Votre code devra être dans le répertoire prévu à cet effet.
- Chaque exercice dans un répertoire (`ex1`, `ex2`, `ex3`, ...).
- Chaque exercice doit posséder son propre `Makefile` pour la compilation.
- Il est impératif de compiler avec les warnings.
- Le `Makefile` ainsi qu'un fichier minimal sera mis à disposition pour chaque exercice.
# Documents
- On fournit:
- Les slides d'algorithmique.
- Les slides de programmation séquentielle.
- Vous pouvez avoir:
- Une feuille A4 recto-verso ***manuscrite***.
# Les exercices
- Deux ou trois parties à chaque énoncé:
- Une partie "théorique" qui décrit les structures de données et fonctionnalités.
- Une partie "technique" qui propose un exemple d'exécution de votre programme avec entrées et sorties.
- Une partie "exemple" (pas obligatoire) où d'autres exemples sont donnés afin de tester l'exécution de votre programme.
- Votre code doit avoir **exactement** le comportement des exemples donnés **sous peine de sanctions**.
- Chaque code doit être **dans un unique fichier .c** (`ex1.c`, `ex2.c`, ...).
- Donc **inutile** d'écrire des fichiers `.h` ou d'avoir d'autres `.c`
# Évaluation (technique)
- L'évaluation se base surtout sur des critères de fonctionnement:
- le code compile-t-il? (on regarde même pas)
- s'exécute-t-il? (on regarde un peu)
- le code demandé est-il réalisé?
- donne-t-il des résultats corrects?
- votre code possède-t-il des comportements indéfinis?
- Si vous laissez des warnings vous serez pénalisé·e·s.
# Évaluation (style)
- Le code est-il joli?
- Présentation (indentation cohérente, variables nommées de façon raisonnable).
- Modularité (utilisation de fonctions).
- Pas de variables globales inutiles.
- Utilisation de boucles, structures de contrôle, struct, ...
- Fonctions récursives, ...
# Les exemples
- Chaque exemple contient:
- un input à rentrer à la ligne de commande (on peut copier-coller l'input de l'énoncé).
- un output à écrire dans le terminal (on peut comparer la sortie avec celle de l'énoncé).
- La structure de l'input doit être **exactement** la même que celle décrite dans l'énoncé.
- Pour l'input il faut impérativement utiliser `argc` et `argv[]`.
- L'output de vos exercices doit être celui de l'énoncé.
Et maintenant place à des exemples (simplifiés)!
# Exercice 1
Ce programme prend en argument deux entiers et affiche
leur somme sur une nouvelle ligne.
## Exemple
```bash
$ ./prog 12 19
31
```
# Exercice 2
\footnotesize
Ce programme prend en argument un nombre entier `N` puis des nombres à virgule flottante.
Il y aura exactement `N` nombres à virgule flottante.
Ensuite, votre programme multiplie chaque nombre à virgule flottante par deux et affiche la somme
sur une nouvelle ligne suivi de CHF.
## Exemple
```bash
$ ./prog 12 12.2 45.5 1.5 65.1 89.4 567.6 112.8 67.0 35.1 112.2 3.3 9.8
2243.000000 CHF
```
# Exercice 3
Ce programme prend en argument 2 chaînes de caractères (longueur max de 80),
les sépare au milieu et retourne les 4 chaînes chacune sur une nouvelle ligne
(si la longueur N est paire on sépare en 2 chaînes de longueur N/2, sinon la première
aura une longueur de N/2 et la seconde N/2+1).
## Exemple
```bash
./prog abcdefgh asdfghjkl
abcd
efgh
asdf
ghjkl
```
---
title: "Lecture/écriture de fichiers"
date: "2023-12-14"
---
# Les fichier en C
* Un fichier en C est représenté par un pointeur de fichier.
```C
#include <stdio.h>
FILE *fp;
```
* `FILE *`{.C} est une structure de donnée *opaque* contenant les informations sur l'état du fichier.
* Il est manipulé à l'aide de fonctions dédiées.
* Le pointeur de fichier est toujours passé *par copie*.
# Manipulations de fichier
* Pour lire/écrire dans un fichier il faut toujours effectuer trois étapes:
1. Ouvrir le fichier (`fopen()`{.C}).
2. Écrire/lire dans le fichier (`fgets()`{.C}, `fputs()`{.C}, `fread()`{.C}, `fwrite()`{.C}, ...).
3. Fermer le fichier (`fclose()`{.C}).
* Nous allons voir brièvement ces trois étapes.
# Ouverture d'un fichier
* L'ouverture d'un fichier se fait avec la fonction `fopen()`{.C}
```C
FILE *fp = fopen(filename, mode);
```
* `filename`{.C} est une chaîne de caractères (incluant le chemin).
* `mode`{.C} est le mode d'ouverture (`"r"`{.C}, `"w"`{.C}, ... voir `man 3 fopen`{.bash}) qui est une chaîne de caractères.
* Si l'ouverture échoue (pas la bonne permission, ou n'existe pas) `fopen()`{.C} retourne `0`.
* **Toujours** tester le retour de `fopen()`{.C}
```C
if (NULL == fp) {
fprintf(stderr, "Can't open output file %s!\n",
filename); // affiche dans le canal d'erreur
exit(EXIT_FAILURE);
}
```
# Fermeture d'un fichier
* Il faut **toujours** fermer un fichier à l'aide de `fclose()`{.C}
```C
FILE *fp = fopen("mon_fichier", "w");
// écritures diverses
fclose(fp);
```
* Les données sont transférées dans une mémoire tampon, puis dans le disques.
* Si la mémoire tampon est pleine, le fichier est fermé, ... les données sont écrites sur le disque.
* Si la mémoire tampon contient encore des données à la fin du programme les données sont **perdues**.
# Lecture d'un fichier (1/2)
```C
char *fgets(char *s, int size, FILE *stream)
```
* Lit une ligne de taille d'au plus `size-1` et la stocke dans `s`, depuis `stream`.
* Retourne `s` ou `NULL` si échoue.
```C
FILE *fp = fopen("text.txt", "r");
char buffer[100];
fgets(buffer, 37, fp);
// lit 36 caractères au plus et les écrit dans buffer
// s'arrête si rencontre EOF, ou "\n".
// ajoute un "\0" terminal
fclose(fp);
```
# Lecture d'un fichier (2/2)
```C
size_t fread(void *ptr, size_t size, size_t nmemb,
FILE *stream)
```
* Lit `nmemb` éléments de taille `size` octets et les écrit à l'adresse `ptr` dans le fichier `stream`.
* Retourne le nombre d'éléments lus.
```C
FILE *fp = fopen("doubles.bin", "rb");
double buffer[100];
size_t num = fread(buffer, sizeof(double), 4, fp);
// lit 4 double, se trouvant dans le fichier fp au
// format binaire et les écrit dans buffer, puis
// retourne 4
fclose(fp);
```
# Écriture dans un fichier (1/2)
```C
int fprintf(FILE *stream, const char *format, ...)
```
* Écrit la chaîne de caractères `format` dans le fichier stream.
* `format` a la même syntaxe que pour `printf()`.
* Retourne le nombre de caractères écrit sans le `\0` terminal(si réussite).
```C
FILE *fp = fopen("text.txt", "w");
fprintf(fp, "Hello world! We are in %d\n", 2020);
// Écrit "Hello world! We are in 2020"
// dans le fichier fp
fclose(fp);
```
# Écriture dans un fichier (2/2)
```C
size_t fwrite(const void *ptr, size_t size,
size_t nmemb, FILE *stream)
```
* Écrit `nmemb` éléments de taille `size` octets se trouvant à l'adresse `ptr` dans le fichier `stream`.
* Retourne le nombre d'éléments écrits.
```C
FILE *fp = fopen("doubles.bin", "wb");
double buffer[] = {1.0, 2.0, 3.0, 7.0};
size_t num = fwrite(buffer, sizeof(double), 4, fp);
// écrit 4 double, se trouvant à l'adresse
// buffer dans le fichier fp au format binaire
// retourne 4
fclose(fp);
```
# Les pointeurs de fichiers spéciaux
* Il existe trois `FILE *`{.C} qui existent pour tout programme:
* `stdin`{.C}: l'entrée standard.
* `stdout`{.C}: la sortie standard.
* `stderr`{.C}: l'erreur standard.
* Lors d'un fonctionnement dans le terminal:
* l'entrée standard est le *clavier*
* la sortie et erreur standard sont affichés dans le *terminal*.
* Ainsi on a
```C
fprintf(stdout, "texte\n"); // == printf("texte\n");
int a;
fscanf(stdin, "%d", &a); // == scanf("%d", &a);
```
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="245.24887mm"
height="86.080841mm"
viewBox="0 0 245.24887 86.080843"
version="1.1"
id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="pointer_struct_ok.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="483.38263"
inkscape:cy="105.54084"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1884"
inkscape:window-height="1052"
inkscape:window-x="36"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
originy="-104.07588"
originx="12.489411"
type="xygrid"
id="grid819" />
</sodipodi:namedview>
<defs
id="defs2">
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker3314"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path3312" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker3284"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path3028" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="Arrow2Lstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lstart">
<path
inkscape:connector-curvature="0"
transform="matrix(1.1,0,0,1.1,1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path3025" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="Arrow2Lend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path8951" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="Arrow2Lend-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path8951-5"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="Arrow2Lend-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path8951-8"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="Arrow2Lend-7-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path8951-5-8"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="Arrow2Lend-1"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path8951-3"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker3284-4"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path3028-7" />
</marker>
</defs>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(12.489412,-106.8433)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<g
style="fill:none;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="g846-7-2"
transform="matrix(0.48784069,0,0,1,-44.968279,-20.032731)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-3-5-2"
width="29.104166"
height="9.260417"
x="99.218758"
y="156.77083" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-6-3-8"
width="29.104166"
height="9.260417"
x="128.32292"
y="156.77083" />
</g>
<g
style="fill:none;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="g846-5-1"
transform="matrix(0.48784069,0,0,1,-16.571887,-20.032726)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-3-6-9"
width="29.104166"
height="9.260417"
x="99.218758"
y="156.77083" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-6-2-4"
width="29.104166"
height="9.260417"
x="128.32292"
y="156.77083" />
</g>
<g
id="g1489"
transform="translate(-82.051746)">
<g
transform="matrix(0.4878407,0,0,1,93.949527,-20.032732)"
id="g846-7-2-6"
style="fill:none;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<rect
y="156.77083"
x="99.218758"
height="9.260417"
width="29.104166"
id="rect821-3-5-2-7"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="156.77083"
x="128.32292"
height="9.260417"
width="29.104166"
id="rect821-6-3-8-5"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
transform="matrix(0.4878407,0,0,1,122.34592,-20.032727)"
id="g846-5-1-9"
style="fill:none;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<rect
y="156.77083"
x="99.218758"
height="9.260417"
width="29.104166"
id="rect821-3-6-9-1"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="156.77083"
x="128.32292"
height="9.260417"
width="29.104166"
id="rect821-6-2-4-2"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2993"
d="M -1.3502974,178.91256 C -10.434806,165.66351 -12.664615,164.59117 0.16160744,145.99852"
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3284)" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2993-6"
d="M -1.6432048,189.1699 C -12.064062,177.52447 -18.226203,141.46875 -3.5290926,116.46165"
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3284-4)" />
<g
id="g1518"
transform="translate(3.2072343)">
<g
transform="matrix(0.48784068,0,0,1,-23.535649,-49.569597)"
id="g846-7-2-5"
style="fill:none;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.7158648, 1.43172961;stroke-dashoffset:0;stroke-opacity:1">
<rect
y="156.77083"
x="99.218758"
height="9.260417"
width="29.104166"
id="rect821-3-5-2-6"
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.7158648, 1.43172961;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="156.77083"
x="128.32292"
height="9.260417"
width="29.104166"
id="rect821-6-3-8-9"
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.7158648, 1.43172961;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:0.50000001, 1.00000003;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-3-6-7-37"
width="14.198196"
height="9.260417"
x="-3.5290926"
y="107.20123" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#0000ff;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:0.50000001, 1.00000003;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-6-2-3-4"
width="14.198196"
height="9.260417"
x="10.669104"
y="107.20123" />
<g
transform="translate(-85.25898)"
id="g1481">
<g
style="fill:none;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.71586478, 1.43172956;stroke-dashoffset:0;stroke-opacity:1"
id="g846-7-2-6-4"
transform="matrix(0.48784071,0,0,1,90.258825,-49.569599)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.71586478, 1.43172956;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-3-5-2-7-3"
width="29.104166"
height="9.260417"
x="99.218758"
y="156.77083" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.71586478, 1.43172956;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-6-3-8-5-0"
width="29.104166"
height="9.260417"
x="128.32292"
y="156.77083" />
</g>
<g
style="fill:none;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.71586478, 1.43172956;stroke-dashoffset:0;stroke-opacity:1"
id="g846-5-1-9-8"
transform="matrix(0.48784071,0,0,1,118.65522,-49.569594)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.71586478, 1.43172956;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-3-6-9-1-4"
width="29.104166"
height="9.260417"
x="99.218758"
y="156.77083" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0007;stroke-width:0.71586478;stroke-miterlimit:4;stroke-dasharray:0.71586478, 1.43172956;stroke-dashoffset:0;stroke-opacity:1"
id="rect821-6-2-4-2-3"
width="29.104166"
height="9.260417"
x="128.32292"
y="156.77083" />
</g>
</g>
</g>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.61108494px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.24027713"
x="2.3449361"
y="132.47079"
id="text1455"><tspan
sodipodi:role="line"
id="tspan1453"
x="2.3449361"
y="132.47079"
style="stroke-width:0.24027713">fraction_t</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.26458332"
x="2.2523637"
y="155.76122"
id="text1459"><tspan
sodipodi:role="line"
id="tspan1457"
x="2.2523637"
y="155.76122"
style="stroke-width:0.26458332">num</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.26458332"
x="59.490494"
y="155.76122"
id="text1463"><tspan
sodipodi:role="line"
id="tspan1461"
x="59.490494"
y="155.76122"
style="stroke-width:0.26458332">denom</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.47521019px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.21188024"
x="0.21260698"
y="181.14244"
id="text1467"><tspan
sodipodi:role="line"
id="tspan1465"
x="0.21260698"
y="181.14244"
style="stroke-width:0.21188024">fraction_t *frac = malloc(sizeof(fraction_t));</tspan><tspan
sodipodi:role="line"
x="0.21260698"
y="191.73645"
style="stroke-width:0.21188024"
id="tspan1471">frac = NULL; // addresse mémoire inaccessible</tspan></text>
</g>
</svg>
This diff is collapsed.
This diff is collapsed.
......@@ -59,7 +59,7 @@ struct fraction frac; // déclaration de frac
- `typedef`{.C} permet de définir un nouveau type.
```C
typedef unsinged int uint;
typedef unsigned int uint;
typedef struct fraction fraction_t;
typedef struct fraction {
int32_t num, denom;
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment