0% ont trouvé ce document utile (0 vote)
18 vues24 pages

Compilation C

Le document présente le contexte historique du langage C en décrivant l'évolution des microprocesseurs et le passage du code assembleur aux octets. Il contient également un plan détaillé du document.

Transféré par

heritianarazafy2004
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
18 vues24 pages

Compilation C

Le document présente le contexte historique du langage C en décrivant l'évolution des microprocesseurs et le passage du code assembleur aux octets. Il contient également un plan détaillé du document.

Transféré par

heritianarazafy2004
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Plan

1 Contexte 4 Particularités du langage


2 Le C : un langage compilé et modulaire Le programme principal
3 Éléments de base du langage Pointeurs de fonction
Langage C La base Les bibliothèques
Les pointeurs Les macros paramétrés (macro-
Entrée / Sortie standard fonction)
Nicolas Delestre Les types composites Mots clés
Les fichiers Arithmétique sur les pointeurs
Allocation statique et dynamique
Les chaı̂nes de caractères
5 La bibliothèque standard
Préconditions : errno.h
Préconditions : assert.h

Le langage C - v3.0.1 1 / 93 Le langage C - v3.0.1 2 / 93

Contexte Contexte

Sous le capot d’un PC Processeur, microprocesseur


Définitions
≪ Un processeur est la partie d’un ordinateur qui exécute les instructions et traite les

Ports (USB, HDMI, etc.) données des programmes. (Wikipédia)


≪ Un microprocesseur est un processeur dont tous les composants ont été suffisamment
miniaturisés pour être regroupés dans un unique boı̂tier ≫ (Wikipédia)

Processeur Caractéristique d’un microprocesseur


Bus
Le jeu d’instructions
La complexité de son architecture (nb de cœurs,
transitors)
Mémoire vive Le nombre de bits que le processeur peut traiter
simultanément
La vitesse de l’horloge
Le langage C - v3.0.1 3 / 93 Le langage C - v3.0.1 4 / 93
Contexte Contexte

Un peu d’histoire Du code assembleur aux octets

Évolutions des microprocesseurs Tout est octet


Année Fabriquant Nom Nb instructions Nb transistors Fréquence Nb bits Les programmes et les données sont représentés par des octets et stockés dans la mémoire vive
1971 Intel 4004 46 2 300 108 kHz 4/4 Chaque instruction d’un microprocesseur est représentée par un ou plusieurs octets : codage
1974 Intel 8080 72 6 000 2 MHz 8/8
1979 Intel 8088 72 29 000 5 MHz 16/32 Les octets représentants le programme se nomment le code objet
1979 Motorola 68000 82 68 000 2 à 12 MHz 16/32
1982 Intel 80286 99 134 000 6 à 16 MHz 16/16 Le langage assembleur est une représentation humainement compréhensible du code objet :
1983 Acorn ARM1 ≈ 50 25 000 ≤ 8 MHz 32/26
1985 Intel 80386 155 275 000 16 à 40 32/32 assembler : code assembleur → code objet
1992 IBM PowerPC 601 2 800 000 50 à 120 MHz 32/32 désassembler : code objet → code assembleur
1993 Intel Pentium 168 3 100 000 60 à 233 MHz 32/64
1995 AMD K5 168 4 300 000 75 à 100 MHz 32/64
.
.
.
.
.
.
.
.
.
.
.
.
.
. Exemple pour x86
. . . . . . .
2021 IBM Power10 3 600 000 000 4 GHz 64 $ objdump -d helloworld.o
2022 Intel i9 12900H 981 4 150 000 000 5 GHz 64 helloworld.o: format de fichier elf64-x86-64
2022 Apple M2 (ARMV8-5) “232” 20 000 000 000 ≤ 3,4 GHz 64
Déassemblage de la section .text :
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
Remarques 4:
8:
48
48
83
8d
ec
3d
08
00 00 00 00
sub
lea
$0x8,%rsp
0x0(%rip),%rdi # f <main+0xf>
f: e8 00 00 00 00 callq 14 <main+0x14>
Apple a souvent changé de microprocesseur pour ces Mac : 1984 Motorola, 1995 IBM, 2005 Intel, 2020 ARM 14:
19:
b8
48
00
83
00
c4
00 00
08
mov
add
$0x0,%eax
$0x8,%rsp
1d: c3 retq
Il est difficile de connaı̂tre le nombre de transistors dans les nouveaux microprocesseurs

Le langage C - v3.0.1 5 / 93 Le langage C - v3.0.1 6 / 93

Contexte Contexte

Langage de plus haut niveau et compilation 1 / 3 Langage de plus haut niveau et compilation 2 / 3
Constats
Le code assembleur est propre à chaque microprocesseur Gain en productivité
Il est très difficile d’écrire un code conséquent en assembleur Plus simple
⇒ Nécessité de développer avec des langages de plus haut niveau qu’un programme va Abstraction
traduire en code assembleur / code objet
Permet le changement de paradigme
Compilation vs interprétation Des contrôles (sécurité) peuvent être ajoutés
Traduction à la volée : langage interprété ⇒ Une instruction de haut niveau peut produire plusieurs instructions assembleur
Traduction complète du code : langage compilé
Compilation = vérifications avant exécution
Syntaxique : respect de la grammaire du langage
# include <stdio.h> endbr64 f3 0f 1e fa
✩0x8,%rsp
int main(){
sub
lea 0x0(%rip),%rdi
48
48
83
8d
ec
3d
08
00 00 00 00 Sémantique : respect du typage dans les opérations et les passages de paramètre
printf("Hello world\n"); callq 14 <main+0x14> e8 00 00 00 00
} mov ✩0x0,%eax b8 00 00 00 00
add ✩0x8,%rsp 48 83 c4 08
retq c3

Le langage C - v3.0.1 7 / 93 Le langage C - v3.0.1 8 / 93


Contexte Un langage. . .

Langage de plus haut niveau et compilation 3 / 3 Le langage C

Portabilité
Caractéristiques
Un code peut être compilé/interprété sur différents types de microprocesseurs (et de
systèmes d’exploitation) Langage compilé inventé en 1972 par Dennis Ritchie et Kenneth Thompson pour
redévelopper le système d’exploitation UNIX
Langage d’assez bas niveau parmi les langages de haut niveau
endbr64 f3 0f 1e fa
sub
lea
✩0x8,%rsp
0x0(%rip),%rdi
48
48
83
8d
ec
3d
08
00 00 00 00
Normalisé en 1989 (ANSI) et en 1990 (ISO, C90)
callq 14 <main+0x14> e8 00 00 00 00
x86 mov
add
✩0x0,%eax
✩0x8,%rsp
b8
48
00
83
00
c4
00 00
08
Deux nouvelles versions de la norme ISO en 1999 (C99) et 2011 (C11)
# include <stdio.h>
retq c3
int main(){
printf("Hello world\n");
Langage du paradigme de la programmation structurée
}
stp x29, x30, [sp, #-16]! a9 bf 7b fd Langage à typage statique et typage faible
ARM mov
adrp
x29, sp
x0, 0 <main>
91
90
00
00
03
00
fd
00
add
bl
x0, x0, #0x0
0 <puts>
91
94
00
00
00
00
00
00
Le cœur du C comprend peu d’instructions, mais il est accompagné de nombreuses
mov
ldp
w0, #0x0
x29, x30, [sp], #16
52
a8
80
c1
00
7b
00
fd bibliothèques standards
ret d6 5f 03 c0

Le langage C - v3.0.1 9 / 93 Le langage C - v3.0.1 10 / 93

Un langage. . . Un langage. . .

Le C un langage compilé GCC


Compilation d’un fichier C
Objectif : produire à partir d’un fichier .c (code source) un fichier .o (code objet)
Le code source est composé de deux langages : macros (instructions commençant par un ✩ ls
#) et code C helloworld.c
✩ gcc -c helloworld.c
pr écompilation compilation
code source avec macros −−−−−−−−→ code source sans macros −
−−−−−−
→ code objet ✩ ls
helloworld.c helloworld.o
La .o n’est pas un exécutable !

Plusieurs compilateurs Options à utiliser


GCC (GNU Compiler Collection) -Wall pour afficher tous les warnings
intel -pedantic pour n’accepter que du code C ISO
Clang
Microsoft Visual C++ ✩ gcc -c -pedantic -Wall helloworld.c
✩ ls
https://en.wikipedia.org/wiki/List_of_compilers#C_compilers helloworld.c helloworld.o

Le langage C - v3.0.1 11 / 93 Le langage C - v3.0.1 12 / 93


Un langage. . . Un langage. . .

L’édition des liens Deux types de bibliothèques

Constats sur l’exemple


Bibliothèque statique (.a sous Unix, .lib sous Windows)
Le .o n’est pas un exécutable !
Le code objet de la bibliothèque est ajouté au code objet du programme et le lien entre l’appel du sous
Le cœur du langage C propose peu de fonctionnalités programme et le corps du sous programme est réalisé à l’édition des liens
Le code correspondant à l’affichage d’une chaine de caractères (code de printf) n’est Avantage : chaque programme à sa version d’une bibliothèque

pas inclus dans le .o Inconvénients : exécutable plus volumineux et une même version d’une bibliothèque peut être présente plusieurs
fois en mémoire
Il faut donc lier l’appel du sous programme printf du code objet de helloworld.o avec
le code de ce sous programme, code qui se trouve dans une bibliothèque Bibliothèque dynamique (.so sous Unix, .dll sous Windows)
Le code objet de la bibliothèque est chargé en mémoire de l’ordinateur au lancement du programme (si ce n’est
⇒ L’édition des liens déjà fait) et le lien entre l’appel du sous programme et le corps du sous programme est réalisé à l’exécution
Avantage : une bibliothèque utilisée par plusieurs programmes n’est présente qu’une seule fois en mémoire
Inconvénients : gestion de plusieurs versions d’une bibliothèque et problème si la bibliothèque n’est pas pré installée
pr écompilation compilation édition des liens
code source avec macros −−−−−−−−→ code source sans macros −
−−−−−−
→ code objet −
−−−−−−−−−
→ exécutable

Le langage C - v3.0.1 13 / 93 Le langage C - v3.0.1 14 / 93

Un langage. . . Un langage. . .

L’édition des liens avec gcc sous UNIX Principales bibliothèques standards
Les bibliothèques sous UNIX
Le nom du fichier commence par lib
L’extension du fichier est .a ou .so Fichiers Entêtes Fonctionalités
libc.so assert.h macro assert pour activer des préconditions en mode debug
L’édition des liens avec gcc errno.h codes d’erreur ”renvoyés” par les fonctions standards
option -l suivi du nom de la bibliothèque (sans lib, sans l’extension) limits.h constantes bornes min et max des int
stdargs.h pour créer des fonctions à arité variable
le code objet
stdlib.h transtypage, nombres aléatoires, allocations de mémoire, . . .
option -o pour préciser le nom de l’exécutable (par défaut a.out) stdio.h gestion des entrées/sorties
... ...
Création et exécution du programme helloworld
libm.so complex.h manipulation des nombres complexes
✩ ls ✩ ls math.h fonctions mathématiques (trigo, exp, etc.)
helloworld.c helloworld.o helloworld helloworld.c helloworld.o
✩ gcc -o helloworld -lc helloworld.o ✩ ./helloworld
Hello world

Le langage C - v3.0.1 15 / 93 Le langage C - v3.0.1 16 / 93
Un langage. . . Un langage. . .

Synthèse Quelques remarques

.a
Sous UNIX, la libc est par défaut incluse au système (donc optionnelle)
Si le programme n’utilise aucun module/bibliothèque (outre libc), on peut compiler et
.c .o linker directement en utilisant gcc suivi du fichier C (avec optionnellement l’option -o),
int main() {...} par exemple :
gcc -o helloworld helloworld.c
prg
Il est fortement conseillé d’ajouter l’option -Wall pour avoir tous les warnings
.c .o
L’option -pedantic permet de s’assurer que le code C est ISO

.c .o

Le langage C - v3.0.1 17 / 93 Le langage C - v3.0.1 18 / 93

Éléménts. . . La base Éléménts. . . La base

Les types simples Les variables


Le C propose les types simples suivants :
int a , float, double, char b On déclare en C une variable en la précédant de son type et en la suivant optionnellement
On peut donc suivre les règles de traduction suivantes : d’une initialisation

a. On peut lui adjoindre les qualificatifs short, long ou long long (sur architecture 64bits)
b. On peut leur adjoindre les qualificatifs signed ou unsigned int a;
float x=1.0;
char c;
Algo. ⇒ C
Algorithmique C
Entier,Naturel int, long, short Une variable globale est définie en dehors de toute fonction
Sa portée est le fichier où elle est définie à partir de sa définition (pas au dessus)
Réel float, double
Caractère char Une variable locale est définie à l’intérieur d’une fonction
Booléen int (1=VRAI, 0=FAUX) Sa portée est uniquement la fonction où elle a été définie
Chaı̂ne de caractères Voir les tableaux et pointeurs
Le langage C - v3.0.1 19 / 93 Le langage C - v3.0.1 20 / 93
Éléménts. . . La base Éléménts. . . La base

Définir un type alias Les énumérés

enum
Permet de définir un ensemble de valeurs constantes associées à un type
typedef Syntaxe
Transforme la déclaration d’une variable en déclaration d’un nouveau type enum [nom] {id1 [=val1], id2 [=val2 ], ...}
Syntaxe :
typedef declaration
enum crée un type dont le nom commence par enum
L’utilisation de enum est souvent couplé avec typedef
typedef int Entier ;

typedef enum {LUNDI,MARDI,MERCREDI,JEUDI,VENDREDI,SAMEDI,DIMAMCHE} Semaine;


Semaine unJour = LUNDI;

Le langage C - v3.0.1 21 / 93 Le langage C - v3.0.1 22 / 93

Éléménts. . . La base Éléménts. . . La base

Les constantes 1 / 2 Les constantes 2 / 2


Constantes entières Constantes flotantes
Pour traduire les constantes entières, le C propose trois notations : Pour les constantes flotantes, on utilise le “.” pour marquer la virgule et le caractère “e”
suivi d’un nombre entier, ici a, pour représenter 10a , par exemple :
1 La notation décimale, en base dix, par exemple 379
2. , .3, 2e4, 2.3e4
2 La notation octale, en base huit, qui doit commencer par un zéro par exemple 0573
3 Le notation hexadécimale, en base seize, qui doit commencer par un zéro suivi d’un x Constantes chaı̂ne de caractères
(ou X), par exemple 0X17B (ou 0x17B, 0X17b, 0x17b) Les constantes chaı̂ne de caractères doivent être entourées de guillemets, par exemple ”une
chaine”
Constantes caractères Par défaut le compilateur ajoute à la fin de la chaı̂ne de caractères ’\0’, qui est le marqueur de
Les constantes caractères sont entourées de quote, par exemple ’a’ fin de chaı̂ne
Certains caractères (les caractères non imprimables, avec un code ASCII inférieur à 32,
le \, le ’) ne sont utilisables qu’en préfixant par un \ : Il n’y a pas véritablement de constante nommée en C, on utilise commande #define du
le code ASCII du caractère (exprimé en octal), par exemple ’\001’ préprocesseur
un caractère tel que ’\n’, ’\t’, ’\\’, ’\”’
Toutefois il y a le qualificatif const (pour variable ou paramètre formel)
Le langage C - v3.0.1 23 / 93 Le langage C - v3.0.1 24 / 93
Éléménts. . . La base Éléménts. . . La base

Les opérateurs 1 / 2 Les opérateurs 2 / 2

Algo. ⇒ C
On traduit les opérateurs en respectant les règles suivantes : Opérateurs ++ et −−
Algorithmique C Les opérateurs unaires ++ et −− sont des opérateurs particuliers qui peuvent avoir jusqu’à
deux effets de bord :
=, ̸= ==, !=
En dehors de toute affectation, elle incrémente l’opérande associée, par exemple
<, ≤, >, ≥ <, <=, >, >=
i++ et ++i sont équivalents à i=i+1
et, ou, non &&, ||, !
Lorsqu’ils sont utilisés dans une affectation, tout dépend de la position de l’opérateur par rapport
+, -, *, / +, -, *, /
à l’opérande, par exemple :
div, mod /, %
j=i++ est équivalent à j=i;i=i+1;
j=++i est équivalent à i=i+1;j=i;
Attention
En C l’affectation est une opération (opérateur =)

Le langage C - v3.0.1 25 / 93 Le langage C - v3.0.1 26 / 93

Éléménts. . . La base Éléménts. . . La base

Les instructions Les conditionnelles 1 / 4


Instructions simples if
Elles finissent toujours par un ’ ;’ L’instruction si...alors...sinon est traduite par l’instruction if, qui a la syntaxe
suivante :
Exemple if ( condition )
// instruction (s) du if
a=a+1;
[ else
// instruction (s) du else
Instructions composées ]
Les instructions composées qui permettent de considérer une succession d’instructions
comme étant une seule instruction. Exemple
Elles commencent par “{” et finissent par “}”
if (a<10)
a=a+1;
Exemple else
a=a+2;
{a=a+1;b=b+2;}

Le langage C - v3.0.1 27 / 93 Le langage C - v3.0.1 28 / 93


Éléménts. . . La base Éléménts. . . La base

Les conditionnelles 2 / 4 Les conditionnelles 3 / 4


Attention
Le else dépend toujours du if le plus proche switch...case
L’instruction cas..où est traduite par l’instruction switch, qui a la syntaxe suivante :
Exemple
switch ( leSelecteur ) {
if (a>b) case cas1:
if (c<d) // instruction (s) du cas 1
u=v; break;
else case cas2:
i =j; // instruction (s) du cas 2
break;
...
Le mieux étant toutefois de clarifier cette ambiguité default:
// instruction (s) du default
if (a>b) { }
if (a>b)
if (c<d)
if (c<d) u=v;
u=v;
} else {
else
i =j;
i =j;
}
Le langage C - v3.0.1 29 / 93 Le langage C - v3.0.1 30 / 93

Éléménts. . . La base Éléménts. . . La base

Les conditionnelles 4 / 4 Les itérations 1 / 3


for
L’instruction Pour est traduite par l’instruction for, qui a la syntaxe suivante :
for( initialisation ;
Exemple condition d arret ;
operation effectuée à chaque itération )
switch(choix) { instruction ;
case ’t’ : printf("vous voulez un triangle\n"); break;
case ’c’ : printf("vous voulez un carre\n"); break;
case ’r’ : printf("vous voulez un rectangle\n"); break;
default : printf("erreur. recommencez !\n"); Exemple
}
for(i=0;i<10;i++)
printf("%d\n", i);

Attention
Contrairement à l’algortihmique le for est une itération indéterministe

Le langage C - v3.0.1 31 / 93 Le langage C - v3.0.1 32 / 93


Éléménts. . . La base Éléménts. . . La base

Les itérations 2 / 3 Les itérations 3 / 3


while do..while
L’instruction Tant...que est traduite par l’instruction while, qui a la syntaxe suivante : L’instruction répéter est traduite par l’instruction do..while, qui a la syntaxe suivante :
while( condition ) do
instruction ; instruction ;
while( condition );

Exemple
Exemple
float g,d,m;
g=1; char temp[MAX];
d=x; int motDePasseValide = 0;
while (d-g>epsilon) { int nbEssais = 0;
m=(d+g)/2.0; do {
if (m*m>x) printf("Mot de passe : ");
d=m; scanf("%s", temp);
motDePasseValide = hash(temp) == hashMotPassseRef;
else nbEssais++;
g=m; } while (!motDePasseValide && nbEssais<nbEssaisMax) ;
}

Le langage C - v3.0.1 33 / 93 Attention


Le langage C - v3.0.1 34 / 93

Éléménts. . . Les pointeurs Éléménts. . . Les pointeurs

Les pointeurs 1 / 3 Les pointeurs 2 / 3

Lorsque l’on déclare une variable, par exemple un entier i, l’ordinateur réserve un espace On déclare une variable de type pointeur en préfixant le nom de la variable par le caractère *
mémoire pour y stocker la valeur de i
L’emplacement de cet espace dans la mémoire est nommé adresse int i , j ;
Un pointeur est une variable qui permet de stocker une adresse int ✯p;

Par exemple si on declare une variable entière i (initialisée à 10) et que l’on déclare un Opérateurs * et &
pointeur p dans lequel on range l’adresse de i (on dit que p pointe sur i), on a par exemple Il existe deux opérateurs permettant d’utiliser les pointeurs :
le schéma suivant : 1 & : permet d’obtenir l’adresse d’une variable, permettant donc à un pointeur de pointer sur une variable
2 * : permet de déréférencer un pointeur, c’est-à-dire d’accéder à la valeur de la variable pointée
i p
Mémoire 10 124
p=&i; // p pointe sur i
124 226 ✯p=✯p+2; // ajoute 2 a i
j=✯p; // met la valeur de i dans j (donc 12)

Le langage C - v3.0.1 35 / 93 Le langage C - v3.0.1 36 / 93


Éléménts. . . Les pointeurs Éléménts. . . Les pointeurs

Les pointeurs 3 / 3 Les fonctions 1 / 2

On déclare une fonction en respectant la syntaxe suivante :


Par défaut lorsque l’on déclare un pointeur, on ne sait pas sur quoi il pointe typeRetour nomFonction(type1 param1, type2 param2, ...) {
// variables locales
Comme toute variable, il faut l’initialiser
On peut dire qu’un pointeur ne pointe sur rien en lui affectant la valeur NULL // instructions avec au moins
// une fois l ’ instruction return
}

int i ;
int ✯p1,✯p2;
Par exemple
p1=&i;
p2=NULL;
int plusUn(int a){
return a+1;
}

Le langage C - v3.0.1 37 / 93 Le langage C - v3.0.1 38 / 93

Éléménts. . . Les pointeurs Éléménts. . . Les pointeurs

Les fonctions 2 / 2 Implanter un passage de paramètre en entrée

. . .par un passage de paramètre par valeur


Il n’y a pas de procédure en C On copie la valeur du paramètre effectif dans le paramètre formel :
Pour traduire une procédure, on crée une fonction qui ne retourne pas de valeur, on utilise int carre ( int x){ exemple carre
alors le type void comme type de retour return (x✯x);
}
Tous les passages de paramètres en C sont des passages de paramètres en entrée (on Avant appel i = 3
de carre j = ?
parle de passage par valeur) void exemple (){
int i = 3;
Lorsque l’on veut traduire des passages de paramètres en sortie ou en entrée/sortie on int j ; Au début de l'exécution i = 3 x = 3
utilise les pointeurs (on parle de passage de paramètres par adresse) de carre j = ?
On passe le pointeur sur la variable en lieu et place de la variable j = carre ( i );
printf (”%d\n”,j); À la fin de l'exécution i = 3 x = 3
} de carre j = 9 9

Le langage C - v3.0.1 39 / 93 Le langage C - v3.0.1 40 / 93


Éléménts. . . Les pointeurs Éléménts. . . Entrée / Sortie standard

Implanter un passage de paramètre en entrée/sortie ou en sortie Sortie standard 1 / 2


printf
. . .par un passage de paramètre par adresse L’instruction printf (de la bibliothèque stdio.h) permet d’afficher des informations à
On copie la valeur d’un pointeur sur le paramètre effectif dans le paramètre formel : l’écran
Syntaxe :
void remiseAZero(int ✯p) { exemple remiseAZero
✯p=0; printf (”chaı̂ne de caractères ” [, variables ])
} Avant appel i = 10
de remiseAZero Si des variables suivent la chaı̂ne de caractères, cette dernière doit spécifier comment
void exemple2() { présenter ces variables :
int i =10; Au début de l'exécution %d pour les entiers (int, short, long)
i = 10 p = 124
de remiseAZero &i %f pour les réels (float, double)
remiseAZero(&i);
printf (”%d\n”,i); %s pour les chaı̂nes de caractères
À la fin de l'exécution i = 0 p = 124
} de remiseAZero
%c pour les caractères
La chaı̂ne de caractères peut contenir des caractères spéciaux :
\n pour le retour chariot
\t pour les tabulations

Le langage C - v3.0.1 41 / 93 Le langage C - v3.0.1 42 / 93

Éléménts. . . Entrée / Sortie standard Éléménts. . . Entrée / Sortie standard

Sortie standard 2 / 2 Entrée standard 1 / 2

scanf
Par exemple : L’instruction scanf (de la bibliothèque stdio.h) permet à l’utilisateur de saisir des
informations au clavier
int i =1;
float x=2.0; Syntaxe :
printf (”Bonjour\n”);
scanf(”chaı̂ne de formatage”,pointeur var1 , ...)
printf (”i = %d\n”,i);
printf (”i = %d, x = %f\n”,i,x); La chaı̂ne de formatage spécifie les caractères et le type des données attendues, par
exemple :
. . .affiche : %d pour les entiers (int, short, long)
Bonjour %f pour les réels (float, double)
i=1 %s pour les chaı̂nes de caractères
i = 1, x=2.0 l’espace, la tabulation, le retour chariot sont considéré comme un séparateur de chaı̂ne
préférez dans ce cas gets (voire fgets)
%c pour les caractères

Le langage C - v3.0.1 43 / 93 Le langage C - v3.0.1 44 / 93


Éléménts. . . Entrée / Sortie standard Éléménts. . . Les types composites

Entrée standard 2 / 2 Les tableaux 1 / 2

On déclare une variable de type tableau en ajoutant après l’identificateur la taille de chaque
dimension (entre [ et ])
Par exemple
int i ; int tab1 [10]; // un tableau de 10 entiers (une dimension)
float x; float tab2 [2][5]; // un tableau de 10 réels (deux dimensions)
scanf(”%d%f”,&i,&x);

Le premier indice d’une dimension est toujours 0


C’est vous qui déterminez la sémantique de chaque dimension

Le langage C - v3.0.1 45 / 93 Le langage C - v3.0.1 46 / 93

Éléménts. . . Les types composites Éléménts. . . Les types composites

Les tableaux 2 / 2 Les chaı̂nes de caractères

Une fois déclaré, un élément d’un tableau s’utilise comme une variable classique
Il n’y a pas de type chaı̂ne de caractères en C
int t [10]; // un tableau de 10 entiers (une dimension) Souvent les tableaux de caractères sont utilisés pour les représenter
int i ;
for ( i =0;i<10;i++)
scanf(”%d”,&t[i]);
char nom[30];
printf (”Votre nom: ”);
scanf(”%s”,nom);
Un tableau est considéré comme un pointeur constant
Lors d’un appel de fonction, le passage de paramètre pour un tableau est un passage de
paramètre par adresse Si n caractères sont saisis n + 1 éléments du tableau sont utilisés (’\0’).
Dans la signature d’une fonction, la dimension d’un tableau en tant que paramètre
formel est facultative

Le langage C - v3.0.1 47 / 93 Le langage C - v3.0.1 48 / 93


Éléménts. . . Les types composites Éléménts. . . Les types composites

Les structures Les unions


On traduit une structure en utilisant le mot clé struct Équivalent aux structures sauf que l’espace mémoire réservé est le maximum des espaces
Syntaxe : mémoires des attributs (alors que pour les structures c’est l’addition) a
struct [Nom] { Un seul champ est donc interprétable à un moment donné
type1 attr1 ;
... Syntaxe :
}
union [Nom] {
type1 attr1 ;
...
}
struct Personne {
char nom[30];
char prenom[30]; a. à un alignement près. . .
}

union Nombre {
Attention int unEntier ;
struct crée un nouveau type dont le nom commence par struct float unReel;
Complexe unComplexe;
L’utilisation de struct est souvent couplé avec typedef }
Le langage C - v3.0.1 49 / 93 Le langage C - v3.0.1 50 / 93

Éléménts. . . Les fichiers Particularité. . . Le programme principal

Les fichiers Retour sur la fonction main

En fait la signature de la fonction main est int main(int argc, char **argv), tel que :
Le type FILE* argc est le nombre de paramètres
Pas de concept de fichiers texte ou d’enregistrement : ce sont des fichiers binaires argv est un tableau de chaı̂ne de caractères
Ouverture : FILE *fopen(const char *path, const char *mode); argv[0] est le nom du programme
mode : ”r”, ”r+”, ”w”, ”w+”, ”a”, ”a+”
”b” peut être ajouté pour la compatibilité C89 Exemple : args.c* a
Fermeture : int fclose(FILE *fp)
a. http://www.ai.univ-paris8.fr/~jalb/langimp/main.html
Fonction de lecture : fscanf, fgetc, fgets, fread, . . .
#include <stdio.h>
Fonction d’écriture : fprintf, fputc, fputs, fwrite, . . . #include <stdlib.h>
int main(int argc , char ✯✯argv) {
Fonction gestion curseur : fseek, ftell, rewind, feof, . . . int i ;
printf (”argc: %d\n”, argc);
Pointeurs de fichier prédéfinis : stdin, stdout, stderr for ( i = 0; i < argc; i ++)
printf (”argv[%d]: %s\n”, i, argv [ i ]);
return EXIT SUCCESS;
}

Le langage C - v3.0.1 51 / 93 Le langage C - v3.0.1 52 / 93


Particularité. . . Pointeurs de fonction Particularité. . . Pointeurs de fonction

Pointeurs de fonction Exemple 1 / 3


Tri d’un tableau d’entiers dans un ordre croissant puis décroissant

void triABulle ( int t [], int (✯comparer) (int , int ), int nbElements) {
int i , j , estTrie ;
Les fonctions peuvent être considérées comme des variables, elles possèdent : estTrie =0;
i =0;
un identifiant
while (( i <nbElements) && (!estTrie)) {
un type (type des paramètres et type de retour) estTrie =1;
Elles peuvent être un argument d’un appel de fonction for ( j=nbElements❂1;j>0;j❂❂) {
if (comparer(t[ j ❂1],t [ j])>0) {
echanger(&t[j ❂1],&t[j ]);
estTrie =0;
}
}
i ++;
}
}

Le langage C - v3.0.1 53 / 93 Le langage C - v3.0.1 54 / 93

Particularité. . . Pointeurs de fonction Particularité. . . Pointeurs de fonction

Exemple 2 / 3 Exemple 3 / 3

void afficherTabEntier ( int t [], int nbElements) { int plusGrand(int a, int b) {


int i ; return a<b;
for ( i =0;i<nbElements;i++) }
printf (”%d ”,t[ i ]);
int plusPetit ( int a, int b) {
printf (”\n”);
return a>b;
}
}
void trierEtAfficherTableauDEntiers ( int (✯comparer) (int , int )) {
int main() {
int i ;
trierEtAfficherTableauDEntiers ( plusPetit );
int tabEntier [4];
trierEtAfficherTableauDEntiers (&plusGrand);
for ( i =0;i<4;i++) { }
tabEntier [ i ]=random() % 10;
}
afficherTabEntier ( tabEntier ,4); 3 6 7 5
triABulle ( tabEntier ,comparer,4);
afficherTabEntier ( tabEntier ,4);
3 5 6 7
} 3 5 6 2
6 5 3 2
Le langage C - v3.0.1 55 / 93 Le langage C - v3.0.1 56 / 93
Particularité. . . Les bibliothèques Particularité. . . Les bibliothèques

Les bibliothèques 1 / 3 Les bibliothèques 2 / 3


Le C est un langage modulaire : Comment rendre disponible une bibliothèque ?
Le cœur du C ne contient que le strict minimum
Les extensions sont des bibliothèques
Compiler le(s) .c : obtention de .o (code objet)
Lorsque l’on écrit un programme en C : Inclure le(s) .o dans une bibliothèque :
statique : .a ( .lib sous Windows)
On réutilise des bibliothèques
ex : ar -r libtest.a test1.o test2.o ...
On crée des modules et quelques fois des bibliothèques
dynamique : .so (.dll sous Windows)
Le programme principal est court et utilise ces modules et ces bibliothèques
ex : gcc -o libtest.so -shared test1.o test2.o ...
Comment créer une bibliothèque ou un module ? Rendre disponible le(s) .h et le(s) .a ou .so
Créer un .h qui contient :
la définition des types disponibles Attention
la signature des fonctions disponibles Par abus de langage, on appelle bibliothèque aussi bien le .h que le .a (ou .so)
Créer un .c qui contient : Puisque une bibliothèque (.a ou .so) peut être la concaténation de plusieurs .o,
la définition de types et/ou fonctions privés plusieurs .h peuvent être associés à une bibliothèque
la définition des fonctions déclarées dans le .h
Le langage C - v3.0.1 57 / 93 Le langage C - v3.0.1 58 / 93

Particularité. . . Les bibliothèques Particularité. . . Les bibliothèques

Les bibliothèques 3 / 3 Problème des inclusions multiples 1 / 2


entierA.h
#include ”entierB.h”
typedef int entierA ;
Comment utiliser une bibliothèque ? entierA entierBEnentierA(entierB );

Inclure le .h dans les fichiers (.h ou .c) l’utilisant


À la compilation du projet le .h doit être disponible entierB.h
le référencer en spécifiant dans quel répertoire il se trouve (option -I de gcc) #include ”entierA.h”
À l’édition des liens, le(s) .a (.so) doit(doivent) être disponible(s) typedef int entierB ;
entierB entierAEnentierB(entierA );

Problème
L’interprétation de entierA.h par le préprocesseur va inclure entierB.h, qui va inclure
entierA.h, qui va inclure entierB.h, . . .
Le langage C - v3.0.1 59 / 93 Le langage C - v3.0.1 60 / 93
Particularité. . . Les bibliothèques Particularité. . . Les macros paramétrés (macro-fonction)

Problème des inclusions multiples 2 / 2 Macro définition (macro-fonction) 1 / 4


entierA.h
1 #ifndef __ENTIER_A__ Possibilité de créer des fonctions inline
2 #define __ENTIER_A__
3 typedef int entierA; Syntaxe : #define identifiant(arguments) code
4 #include "entierB.h" Les parenthèses suivent aussitôt l’identifiant
5 entierA entierBEnentierA(entierB); Les paramètres sont séparés par des virgules avec aucun type de spécifié
6 #endif Le code peut être sur plusieurs lignes (utilisation de \ en fin de ligne)
Objectifs :
entierB.h Avoir de la modularité sans appel de fonction : gain de performance, non utilisation de la
pile puisque le code est copié/collé avec les paramètres effectifs qui remplacent les
1 #ifndef __ENTIER_B__ paramètres formels
2 #define __ENTIER_B__ Possibilité d’une sorte de surcharge, même identifiant de macro avec un nombre de
3 typedef int entierB;
4 #include "entierA.h" paramètres formels différents (un warning est produit)
5 entierB entierAEnentierB(entierA);
6 #endif

Le langage C - v3.0.1 61 / 93 Le langage C - v3.0.1 62 / 93

Particularité. . . Les macros paramétrés (macro-fonction) Particularité. . . Les macros paramétrés (macro-fonction)

Macro définition (macro-fonction) 2 / 4 Macro définition (macro-fonction) 3 / 4


Code source
#include <stdlib.h>
#include <stdio.h>
#define ADD(x,y) ((x)+(y))
int main(int argc , char ✯✯argv) {
int milieu , gauche, droite ;
Des problèmes peuvent apparaı̂tre a
scanf(”%d%d”,&gauche,&droite);
milieu = ADD(gauche,droite);
printf (”%d\n”, milieu); a. https ://wiki.deimos.fr/Mieux connaı̂tre et utiliser le préprocesseur du langage C.html
return EXIT SUCCESS;
} Utilisation multiple du paramètre formel
Les conditionnels et itérations avec des macros sur plusieurs lignes
Code produit (extrait)
int main(int argc , char ✯✯argv) {
int milieu , gauche, droite ;
scanf(”%d%d”,&gauche,&droite);
milieu = ((gauche)+(droite));
printf (”%d\n”, milieu);
return 0;
}

Le langage C - v3.0.1 63 / 93 Le langage C - v3.0.1 64 / 93


Particularité. . . Les macros paramétrés (macro-fonction) Particularité. . . Mots clés

Macro définition (macro-fonction) 4 / 4 Mot clé static


Les conditionnels et itérations avec des macros sur plusieurs lignes
#include <stdio.h>
#include <stdio.h> #include <stdlib.h>
#include <stdlib.h>
#define ADD(a, b, c) \
. . .devant la déclaration d’une variable locale
#define ADD(a, b, c) \
printf (”%d + %d ”, a, b); \
printf (”%d + %d ”, a, b); \
c = a + b; \
Permet de conserver l’état de la variable entre deux exécutions d’une fonction
c = a + b; \
printf (”= %d\n”, c);
printf (”= %d\n”, c);
La variable n’est alors initialisée qu’une seule fois
int main(int argc , char ✯argv []) {
int main(int argc , char ✯argv []) {
int i = 0;
int i = 0; int r = 0;
int r = 0;
while (argv [ i ++]) {
while (argv [ i ++])
ADD(r, 1, r );
ADD(r, 1, r ); void foo() {
};
return EXIT SUCCESS;
return EXIT SUCCESS; static int compteurDAppels=0;
}
} compteurDAppels++;
...
}
$ ./a.out 1 2 3
0 + 1 = 1
$ ./a.out 1 2 3
1 + 1 = 2
0 + 1 0 + 1 0 + 1 0 + 1 = 1
2 + 1 = 3
3 + 1 = 4
Le langage C - v3.0.1 65 / 93 Le langage C - v3.0.1 66 / 93

Particularité. . . Mots clés Particularité. . . Mots clés

Mot clé static Mot clé extern a


a. http://www.lri.fr/~aze/page_c/aide_c/

. . .devant la déclaration d’une variable globale ou d’une fonction


Cela permet de spécifier que la variable globale ou la fonction est accessible uniquement Indique que l’emplacement réel et la valeur initiale d’une variable, ou du corps d’un
depuis le fichier où elle est déclarée sous-programme sont définis ailleurs, généralement dans un autre fichier source.
Cela permet d’avoir des variables globales ou des fonctions ayant des même noms dans Cela permet à plusieurs fichiers de se partager une variable ou un sous-programme.
des fichiers différents Pour un prototype de fonction, le mot réservé extern est facultatif.

Le langage C - v3.0.1 67 / 93 Le langage C - v3.0.1 68 / 93


Particularité. . . Arithmétique sur les pointeurs Particularité. . . Allocation statique et dynamique

Arithmétique sur les pointeurs Allocation statique et dynamique

Lorsque l’on déclare une variable locale, le compilateur ajoute des instructions dans le
On peut appliquer les opérateurs +, −, ++ et −− à des variables du type pointeurs code généré réservant de l’espace mémoire dans la pile lorsque la fonction de la variable
sera exécutée
C’est ce que l’on appelle l’allocation statique
int t [10]={1,2,3,4,1,7,2,4,9,60}; Il ajoute aussi du code libérant cet espace mémoire qui sera exécuté lorsque l’on sortira de
int ✯p; la fonction
p=t; On aimerait quelquefois pouvoir déterminer la taille de l’espace mémoire à réserver non
p=p+3; pas à la compilation, mais à l’exécution
✯p=0;
p❂❂; C’est ce que l’on appelle l’allocation dynamique
✯p=10; Elle se fait dans le tas
On réserve l’espace mémoire à l’aide de la fonction malloc (et consoeurs) et on libère cet
espace à l’aide de la fonction free

Le langage C - v3.0.1 69 / 93 Le langage C - v3.0.1 70 / 93

Particularité. . . Allocation statique et dynamique Particularité. . . Les chaı̂nes de caractères

Exemple Chaı̂nes de caractères 1 / 8

void trierEtAfficherTableauDEntiers ( int (✯comparer) (int , int ), int nb) {


int i ; Questions
int ✯ tabEntier ;
Lorsque l’on demande à l’utilisateur de saisir une chaı̂ne de caractères, combien doit on
tabEntier=(int✯)malloc(nb✯sizeof( int ));
for ( i =0;i<nb;i++) { réserver d’espace ?
tabEntier [ i ]=random() % nb; Lorsque l’on veut écrire un fonction qui doit ≪ calculer ≫ une chaı̂ne de caractères, qui
}
afficherTabEntier ( tabEntier ,nb);
réserve l’espace mémoire, l’appelant ou l’appelé ?
triABulle ( tabEntier ,comparer,nb);
afficherTabEntier ( tabEntier ,nb); Réservées où ? comment ?
free ( tabEntier );
} À l’aide d’un tableau de caractères. C’est donc une allocation statique, qui n’a
d’existence que dans le fonction où elle est faite
int main() {
int nb; À l’aide d’une allocation dynamique. Il doit donc y avoir une désallocation quelque part
printf (”nb entier ”);
scanf(”%d”,&nb);
trierEtAfficherTableauDEntiers ( plusPetit ,nb);
trierEtAfficherTableauDEntiers (plusGrand,nb);
} C - v3.0.1
Le langage 71 / 93 Le langage C - v3.0.1 72 / 93
Particularité. . . Les chaı̂nes de caractères Particularité. . . Les chaı̂nes de caractères

Chaı̂nes de caractères 2 / 8 Chaı̂nes de caractères 3 / 8

Premier exemple
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
char✯ saisieQuiNeMarchePas() {
char buffer [MAX]; Exécution
gets( buffer );
return buffer ; $ ./testChaine1
} un petit test qui risque de ne pas marcher
int main(int argc , char ✯✯argv) { un petit test q
printf (”%s\n”,saisieQuiNeMarchePas()); $
return EXIT SUCCESS;
}

Compilation
$ gcc -c -Wall -pedantic testChaine1.c
testChaine1.c: In function ’saisieQuiNeMarchePas’:
testChaine1.c:9:3: attention: cette fonction retourne l’adresse d’une
variable locale [enabled by default]

Le langage C - v3.0.1 73 / 93 Le langage C - v3.0.1 74 / 93

Particularité. . . Les chaı̂nes de caractères Particularité. . . Les chaı̂nes de caractères

Chaı̂nes de caractères 4 / 8 Chaı̂nes de caractères 5 / 8


Deuxième exemple
#include <stdio.h>
#include <stdlib.h>
Exécution
#define MAX 10 $ ./testChaine2
void saisieQuiDevraitMarcher (char buffer []) { ca marche
gets( buffer ); ca marche
} $ ./testChaine2
ca ne marche plus du tout
int main(int argc , char ✯✯argv) { ca ne marche plus du tout
char buffer [MAX]; *** stack smashing detected ***: ./testChaine2 terminated
saisieQuiDevraitMarcher ( buffer ); ======= Backtrace: =========
printf (”%s\n”,buffer); /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7fe72ed77007]
return EXIT SUCCESS; /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x0)[0x7fe72ed76fd0]
}
...

Compilation
$ gcc -c -Wall -pedantic testChaine2.c
$
Le langage C - v3.0.1 75 / 93 Le langage C - v3.0.1 76 / 93
Particularité. . . Les chaı̂nes de caractères Particularité. . . Les chaı̂nes de caractères

Chaı̂nes de caractères 6 / 8 Chaı̂nes de caractères 7 / 8


Troisième exemple
#include <stdio.h>
#include <stdlib.h>
#define MAX 10
void saisieQuiMarche(char buffer []) {
fgets ( buffer ,MAX,stdin);
Exécution
} $ ./testChaine3
un petit test qui marche tres bien
int main(int argc , char ✯✯argv) { un petit
char buffer [MAX];
saisieQuiMarche( buffer );
printf (”%s\n”,buffer);
return EXIT SUCCESS;
}

Compilation
$ gcc -c -Wall -pedantic testChaine3.c
$
Le langage C - v3.0.1 77 / 93 Le langage C - v3.0.1 78 / 93

Particularité. . . Les chaı̂nes de caractères La bibliothèque standard

Chaı̂nes de caractères 8 / 8 La bibliothèque standard

Quatrième exemple
#include <stdio.h>
#include <stdlib.h>
#define MAX 10 Le C standard est livré avec des bibliothèques standards, dont les fichiers d’en-tête sont :
char✯ saisieQuiMarche() { assert.h locale.h stddef.h
char✯ buffer =(char✯)malloc(sizeof(char)✯MAX); ctypes.h math.h stdio.h
fgets ( buffer ,MAX,stdin); setjmp.h
return buffer ;
errno.h stdlib.h
} float.h signal.h string.h
limits.h stdarg.h time.h
int main(int argc , char ✯✯argv) {
char✯ ch;
ch=saisieQuiMarche();
printf (”%s\n”,ch);
free (ch);
return EXIT SUCCESS;
}

Le langage C - v3.0.1 79 / 93 Le langage C - v3.0.1 80 / 93


La bibliothèque standard Préconditions : errno.h La bibliothèque standard Préconditions : assert.h

Erreurs : errno.h Préconditions : assert.h 1 / 2

Gestion des préconditions


On peut faire apparaı̂tre des préconditions en C via l’utilisation de la bibliothèque assert
Gestion des erreurs qui propose la macro
Lorsqu’une fonction ne retourne pas naturellement de valeur (void) ou qu’elle doit assert(expression)
retourner un pointeur, et qu’elle peut produire des erreurs, c’est la valeur de retour qui ≪ Si la macro NDEBUG est définie au moment de la dernière inclusion de <assert.h>, la
indique si une erreur s’est produite : macro assert() ne génère aucun code et ne fait rien. Sinon, la macro assert()
int à la place de void et une valeur différente de 0 est retourné ; affiche un message d’erreur sur la sortie d’erreur et termine l’exécution du programme en
NULL si c’est un pointeur qui est retournée cours en appelant abort() si l’expression est fausse (égale à zéro).
Dans les autres cas, c’est la variable globale errno qui est utilisée Le but de cette macro est d’aider le programmeur à trouver des bogues dans son
application. Le message ‘‘assertion failed in file foo.c, function
do bar(), line 1287’’ n’est d’aucune aide pour l’ utilisateur. ≫ a
a. man

Le langage C - v3.0.1 81 / 93 Le langage C - v3.0.1 82 / 93

La bibliothèque standard Préconditions : assert.h Makefile

Préconditions : assert.h 2 / 2 Compiler un projet C 1 / 3


Un exemple de code : assert.c Organisation d’un projet C
#include <stdio.h> Un projet C est composé de plusieurs répertoires :
/✯ #define NDEBUG src les .c (avec possibilité de sous répertoires), c’est aussi dans ce répertoire que sont mis les .o
décommenter pour annuler les tests
de précondition include les .h
✯/ src/tests les sources des tests unitaires
#include <assert.h>
lib les bibliothèques du projet (.a, .so)
int foo( int a) { bin le(s) exécutable(s)
assert (a>0);
return a; tests les tests unitaires
} doc la documentation technique générée (souvent doc/html et doc/pdf)
int main() {
int i ;
scanf(”%d”,&i);
printf (”%d\n”,foo(i));
Un exemple : programme de tri par minimum successif
}
Composé de :
src/main.c
include/echanger.h, src/echanger.c
Un exemple d’exécution include/triParMinSuccessif.h, src/triParMinSuccessif.c

$ ./assert Objectifs :
-10 lib/libechanger.a
assert: assert.c:10: foo: Assertion ‘a>0’ failed. bin/tri
Abandon (core dumped)

Le langage C - v3.0.1 83 / 93 Le langage C - v3.0.1 84 / 93


Makefile Makefile

Compiler un projet C 2 / 3 Compiler un projet C 3 / 3


Objectifs du makefile
Faciliter :
la compilation, avec vérification des dépendances (si utilisation d’autoconf et automake) et ne
compiler que ce qui est nécessaire
Comment compiler ce projet ? utilisation d’un script bash. . .
l’installation
1 #!/bin/bash
2 gcc -o src/echanger.o -Wall -pedantic -c -Iinclude src/echanger.c la désinstallation
3 ar -r lib/libechanger.a src/echanger.o
4 gcc -o src/triParMinSuccessif.o -Wall -pedantic -c -Iinclude src/triParMinSuccessif.c
5 gcc -o src/main.o -Wall -pedantic -c -Iinclude src/main.c
6 gcc -o bin/tri src/main.o src/triParMinSuccessif.o -Llib -lechanger utilisation classique
./configure
make
make install

le fichier ./configure est généré par des utilitaires (autoconf et automake)


les environnements de développement génèrent automatiquement ces fichiers

Le langage C - v3.0.1 85 / 93 Le langage C - v3.0.1 86 / 93

Makefile Makefile

Écriture d’un makefile à la main 1 / 7 Écriture d’un makefile à la main 2 / 7

Pour plus d’information http://gl.developpez.com/tutoriel/outil/makefile/ Un premier makefile


1 all : bin/tri
Structure du fichier 2
3 bin/tri : lib/libechanger.a src/triParMinSuccessif.o src/main.o
[déclaration de variables] 4
5
gcc -o bin/tri src/main.o src/triParMinSuccessif.o -Llib -lechanger

Règles 6
7
lib/libechanger.a : src/echanger.o
ar -r lib/libechanger.a src/echanger.o
8
9 src/echanger.o : src/echanger.c
10 gcc -o src/echanger.o -c -Wall -pedantic -Iinclude src/echanger.c
Règles 11
12 src/triParMinSuccessif.o : src/triParMinSuccessif.c
Permet de décomposer une action en plusieurs actions 13
14
gcc -o src/triParMinSuccessif.o -c -Wall -pedantic -Iinclude src/triParMinSuccessif.c

15 src/main.o : src/main.c
Structure : 16 gcc -o src/main.o -c -Wall -pedantic -Iinclude src/main.c
17
18 clean :
cible: dependance 19 rm -f bin/*
20 rm -f src/*.o
actions 21 rm -f lib/*.a

Quelques cibles prédéfinies : all, install, clean

Le langage C - v3.0.1 87 / 93 Le langage C - v3.0.1 88 / 93


Makefile Makefile

Écriture d’un makefile à la main 3 / 7 Écriture d’un makefile à la main 4 / 7


Un makefile avec variables
1 SRCDIR=src
2 LIBDIR=lib
3 BINDIR=bin
4 INCLUDEDIR=include
5 CC = gcc
6 AR = ar
Quelques variables internes
7 CFLAGS=-Wall -pedantic -I✩(INCLUDEDIR)
8 LDFLAGS=-L✩(LIBDIR) ✩@ Le nom de la cible de la règle
9 EXEC=tri
10
11 all : ✩(BINDIR)/✩(EXEC)
✩< Le nom de la première dépendance de la règle
12
13 ✩(BINDIR)/tri : ✩(LIBDIR)/libechanger.a ✩(LIBDIR)/triParMinSuccessif.o ✩(LIBDIR)/main.o ✩^ La liste des dépendances de la règle
14 ✩(CC) ✩(LDFLAGS) -o ✩(BINDIR)/✩(EXEC) ✩(LIBDIR)/main.o ✩(LIBDIR)/triParMinSuccessif.o -lechanger
15
16 ✩(LIBDIR)/libechanger.a : ✩(SRCDIR)/echanger.o ✩? La liste des dépendances plus récentes que la cible
17 ✩(AR) -r ✩(LIBDIR)/libechanger.a ✩(SRCDIR)/echanger.o
18
19 ✩(SRCDIR)/echanger.o : ✩(SRCDIR)/echanger.c
✩* Le nom du fichier sans suffixe
20 ✩(CC) -o ✩(SRCDIR)/echanger.o -c ✩(CFLAGS) ✩(SRCDIR)/echanger.c
21
22 ✩(SRCDIR)/triParMinSuccessif.o : ✩(SRCDIR)/triParMinSuccessif.c
23 ✩(CC) -o ✩(SRCDIR)/triParMinSuccessif.o -c ✩(CFLAGS) ✩(SRCDIR)/triParMinSuccessif.c
24
25 ✩(SRCDIR)/main.o : ✩(SRCDIR)/main.c
26 ✩(CC) -o ✩(SRCDIR)/main.o -c ✩(CFLAGS) ✩(SRCDIR)/main.c
27
28 clean :
29 rm ✩(BINDIR)/*
30 rm ✩(SRCDIR)/*.o
Le31langage C rm ✩(LIBDIR)/*.a
- v3.0.1 89 / 93 Le langage C - v3.0.1 90 / 93

Makefile Makefile

Écriture d’un makefile à la main 5 / 7 Écriture d’un makefile à la main 6 / 7


Un makefile avec variables
1 SRCDIR=src
2 LIBDIR=lib
3 BINDIR=bin
4 INCLUDEDIR=include
5 CC = gcc
6 AR = ar
7 CFLAGS=-Wall -pedantic -I✩(INCLUDEDIR) Règles d’inférence
8 LDFLAGS= -L✩(LIBDIR)
9 EXEC=tri
10 Possibilité de généraliser des règles
11 all : ✩(BINDIR)/✩(EXEC)
12
13 ✩(BINDIR)/tri : ✩(LIBDIR)/libechanger.a ✩(SRCDIR)/triParMinSuccessif.o ✩(SRCDIR)/main.o %.o: %.c
14 ✩(CC) ✩(LDFLAGS) -o ✩@ ✩(SRCDIR)/triParMinSuccessif.o ✩(SRCDIR)/main.o -lechanger
15 commandes
16 ✩(LIBDIR)/libechanger.a : ✩(SRCDIR)/echanger.o
17 ✩(AR) -R ✩@ ✩^
18
19 ✩(SRCDIR)/echanger.o : ✩(SRCDIR)/echanger.c
20 ✩(CC) -o ✩@ -c ✩< ✩(CFLAGS)
21
22 ✩(SRCDIR)/triParMinSuccessif.o : ✩(SRCDIR)/triParMinSuccessif.c
23 ✩(CC) -o ✩@ -c ✩< ✩(CFLAGS)
24
25 ✩(SRCDIR)/main.o : ✩(SRCDIR)/main.c
26 ✩(CC) -o ✩@ -c ✩< ✩(CFLAGS)
27
28 clean :
29 rm ✩(BINDIR)/*
30 rm ✩(SRCDIR)/*.o
Le31langage C rm ✩(LIBDIR)/*.a
- v3.0.1 91 / 93 Le langage C - v3.0.1 92 / 93
Makefile

Écriture d’un makefile à la main 7 / 7

Un makefile avec variables


1 SRCDIR=src
2 LIBDIR=lib
3 BINDIR=bin
4 INCLUDEDIR=include
5 CC = gcc
6 AR = ar
7 CFLAGS=-Wall -pedantic -I✩(INCLUDEDIR)
8 LDFLAGS=-L✩(LIBDIR)
9 EXEC=tri
10
11 all : ✩(BINDIR)/✩(EXEC)
12
13 ✩(BINDIR)/tri : ✩(LIBDIR)/libechanger.a ✩(SRCDIR)/triParMinSuccessif.o ✩(SRCDIR)/main.o
14 ✩(CC) ✩(LDFLAGS) -o ✩@ ✩(SRCDIR)/triParMinSuccessif.o ✩(SRCDIR)/main.o -lechanger
15
16 ✩(LIBDIR)/lib%.a : ✩(SRCDIR)/%.o
17 ✩(AR) -r ✩@ ✩^
18
19 ✩(SRCDIR)/%.o : ✩(SRCDIR)/%.c
20 ✩(CC) -o ✩@ -c ✩< ✩(CFLAGS)
21
22 clean :
23 rm ✩(BINDIR)/*
24 rm ✩(SRCDIR)/*.o
25 rm ✩(LIBDIR)/*.a

Le langage C - v3.0.1 93 / 93

Vous aimerez peut-être aussi