Académique Documents
Professionnel Documents
Culture Documents
CSI3 NANTES
BENOIT.LARDEUX@ISEN-OUEST.YNCREA.FR
Plan du chapitre
• Introduction
• Généralités
• Syntaxe de base
• Structures de contrôle
• Les fonctions
• Les tableaux
• Compléments
• Du programme à l'exécutable
Sources
• J.-P. GERVAL, Cours d’Algorithmique non-numérique, ISEN 3ème année
• B. W. Kernighan et D. M. Ritchie, The C Programming Language,
Masson
• B. CASSAGNE, Introduction au langage C, Université Joseph Fourier,
Grenoble
• C. BAC, Support de cours de langage C, INT Evry
• P. TRAU, Langage C, Université de Strasbourg (UdS)
INTRODUCTION
Historique du langage C
• Apparu au cours de l'année 1972 dans les Bell Labs
• Développé par D. Ritchie et K. Thompson
• Inspiré des langages BCPL et B
• Lié à la conception du système d’exploitation UNIX
• UNIX est écrit à 95% en Langage C
• Normalisé en 1989 par l’ANSI
• ANSI C99
• Approuvé par l’ISO en 1990
• ISO C
• Evolution en 1999
• ISO C99
Intérêts
• Basé sur un standard ouvert
• Compilateurs et bibliothèques disponibles sur la plupart des architectures
Intérêts
Intérêts
• Met en œuvre un nombre restreint de concepts
• Simplifie la maitrise et écriture des compilateurs simplifiées
• Langage facile à apprendre
• Langage efficace
• Rapidité d’exécution,
• Faible encombrement des exécutables
Inconvénients
• Peu de vérifications lors de la compilation et aucune vérification
pendant l'exécution (la réussite de la compilation n’assure pas que le
programme fonctionne)
• Exemple : Une allocation mémoire qui passe une compilation mais qui est
trop petite pour le nombre de données allouées
10
GÉNÉRALITÉS
11
Programme principal
Fichier sources
Fichier en-tête
12
Programme principal
• Il s’agit du seul fichier qui contient la fonction main
• C’est le point de démarrage de l’exécutable
test_pi.c
#include <stdio.h> Header de la bibliothèque standard (in/out)
pour la fonction printf
#define PI 3.14 Equivalence, le pre-processeur remplace
tous les PI par 3.14
main(){ /* debut de la fonction main */
13
Compilation simple
• Produire un exécutable
• Lancer l'exécutable
>> a.out : command not found !
>> ./a.out Execute a.out
PI vaut 3.14 Résultat du programme
14
15
test_carre.c
Créer des sous - fonctions
#include <stdio.h> Header de la bibliothèque standard (in/out) pour la fonction printf
#define PI 3.14
Equivalence, le pre-processeur remplace tous les PI par 3.14
float carre( float x ); Déclaration d'une fonction carre prenant comme argument d'entrée
un variable de type float et renvoie en sortie un variable de type float
main(){ /* debut de la fonction main */
Déclaration de la variable locale pi2
float pi2;
Utilisation du sous-programme carré avec comme argument
pi2 = carre( PI );
d'entrée PI. Affectation du résultat à la variable pi2
printf("PI^2 vaut %f", pi2);
Affichage de la variable pi2 à
} /* fin de la fonction main */ l'écran
Définition de la
float carre( float x){ /* début de la fonction carre */ fonction carre
Déclaration d’une variable x2 de type float
float x2;
x2 = x*x; On affecte a x2 le résultat de l'opération x*x
return( x2); On renvoie en sortie de fonction la valeur de la
variable x2
} /* fin de la fonction carré */
16
• Lancer l'exécutable
17
SYNTAXE DE BASE
18
Les commentaires
• Les commentaires débutent par /* et se terminent par */
/* This is a comment */
19
/*! ***************************************************************
File: test_algo.c
Author: BL
*******************************************************************/
20
/*! --------------------------------------------------------------
Function: carre
Interface:
Input
x : input value (float)
Output
NA
Input/Output
NA
-----------------------------------------------------------------*/
21
/*-------------------------------------------------------------
Compute the variance by performing
the average of square values
--------------------------------------------------------------*/
x2 = x*x; /* compute square of x */
y2 = y*y; /* compute square of y */
z2 = z*z; /* compute square of z */
22
23
24
Pseudo-langage
Langage C
variable
a,b,c : Entier int a,b,c;
c : Caractère char c;
25
Déclaration
a : Entier int a = 2;
a 2
26
Opérateurs usuels
• Addition
1 : Evaluation de a et b
c = a + b; 2 : Addition de a et b
c = a - b;
• Multiplication
L'opérateur '/' désigne à la fois la division
c = a * b; entière et là division flottante. Si a et b
sont entiers alors division entière sinon
division flottante
• Division
c = a / b;
• Modulo
c = a % b;
27
Opérateurs de comparaison
• Strictement supérieur
1 : Evaluation de a et b
res = ( a > b );
2 : Comparaison de a e t b, 1 si vrai , 0 sinon
3 : Affectation du résultat dans res
• Supérieur ou égal
res = (a >= b );
• Strictement inférieur
res = ( a < b );
• Inférieur ou égal
res = ( a <= b );
• Egal
res = ( a == b );
Ne pas confondre l'opérateur de
• Différent comparaison '==' et l'opérateur
res = ( a != b ); d'affectation '="
28
Opérateurs spéciaux
29
Syntaxe Description
+= Addition puis affectation i += 1;
-= Soustraction puis affectation i -= 1;
/= Division puis affectation x /= 2;
*= Multiplication puis affectation x *= 2;
30
Syntaxe Description
| OR c = a | b;
^ XOR c = a ^ b;
~ NOT b = ~a;
31
32
#include <stdio.h>
int main(){
int x;
33
Inclusion de sources
34
Fichier Contenu
<stdio.h> Fonctions puts() gets(), printf(), scanf(),…
<limits.h> Indique les limites des types
<string.h> Traitement des chaines, copie, concaténation,
recherche de sous-chaines
<math.h> Fonctions mathématiques
<stdlib.h> Allocation dynamique de mémoire (malloc),
conversion nombre vers ascii,…
<time.h> Fonctions liées à l'heure et la génération des
nombres aléatoires
35
Exemple de nommage….
• Variables locales Renseigne sur le type
• Variables Globales
int MA_VARIABLE_GLOBALE Majuscules !
• Fonctions
36
Exercice 1
Ecrire un programme en langage C qui fait saisir à l’utilisateur 2 entiers et
qui calcule puis affiche la somme des 2 valeurs entrées.
37
Exercice 2
Qu’affiche le programme suivant ?
#include <stdio.h>
#include <stdlib.h>
int main(){
int a = 8;
int b = 14;
int c,d;
a++;
b-=2;
c = a|b;
d = (a<<2) & (b>>1);
printf("c=%x et d=%d",c,d);
return 0;
}
38
STRUCTURES DE CONTRÔLE
39
Séquence
Pseudo-langage
Langage C
Faire
ab a = b;
c d c = d;
Fait
40
Alternative : if
Pseudo-langage
Langage C
si (a = b) alors if( a == b){
... …
sinon }else{
... …
finsi }
int i=2;
if( i == 2){ >> ./a.out
printf("Branche 1"); Branche 1
}else{ Fin
printf("Branche 2"); >>
}
printf("Fin");
41
Pseudo-langage
Langage C
Tant que (a=b) faire while( a == b){
... …
Fin tant que }
42
Pseudo-langage
Langage C
Répéter do{
... …
Jusqu'à (a=b) }while(a == b);
43
Pseudo-langage
Langage C
pour (i 0 à N par pas de 1) faire for(i=0;i<=N;i++){
... …
finpour }
44
Choix multiple
Pseudo-langage Langage C
Selon switch(a){
(a=1) faire case 1 :
… …
fait break;
(a=2) faire case 2 :
… …
fait break;
Sinon faire default :
… …
fait break;
Finselon }
45
46
LES FONCTIONS
47
En C :
fonction addition ( E a, b : Entier) : Entier int addition(int a, int b){
Déclaration s : Entier int s;
Début
s a+b s = a+b;
retourner (s) return( s );
fin addition } 48
Particularités du langage C
• Une fonction ne renvoie pas forcément une donnée en sortie
• Le mot clef void est utilisé pour exprimer l'idée "d'aucune valeur"
49
func.c
void main(){
int c; #include "func.h"
… int maFonction(int a,int b){
c = maFonction ( a, b); …
… }
}
main.c
int maFonction(int a,int b){
… #include "func.h"
} void main(){
int c;
…
c = maFonction ( a, b);
}
50
Utilisation
void main(){
int c;
…
c = monAddition( 1, 2)
…
}
51
Utilisation
void main(){
int c = 0;
monAddition2( 1, 2, &c)
}
52
Définition mémoire
void monAddition2( int a , int b , int* pc ){ 0xD0 -
int c = 0;
0xD4 -
c = a + b;
*pc = c; 0xD8 -
}
0xDC -
0xE0 -
Utilisation 0xE4 -
void main(){ 0xE8 -
int c = 0;
monAddition2( 1, 2, &c) 0xEC -
} 0xF0 -
0xF4 -
0xF8 -
53
Définition mémoire
void monAddition2( int a , int b , int* pc ){ 0xD0 -
int c = 0;
0xD4 -
c = a + b;
*pc = c; 0xD8 0
}
0xDC -
0xE0 -
Utilisation 0xE4 -
&c = 0xD8
void main(){ 0xE8 -
int c = 0;
monAddition2( 1, 2, &c) 0xEC -
} 0xF0 -
0xF4 -
0xF8 -
54
Définition mémoire
void monAddition2( int a , int b , int* pc ){ 0xD0 -
int c = 0;
0xD4 -
c = a + b;
*pc = c; 0xD8 0
}
0xDC -
0xE0 -
Utilisation 0xE4 -
void main(){ 0xE8 -
int c = 0;
monAddition2( 1, 2, &c) 0xEC -
} 0xF0 -
0xD8
0xF4 -
0xF8 -
55
56
Définition mémoire
void monAddition2( int a , int b , int* pc ){ 0xD0 -
int c = 0;
&c_i = 0xF8 0xD4 -
c = a + b;
*pc = c; 0xD8 0
}
0xDC -
0xE0 -
Utilisation 0xE4 -
void main(){ 0xE8 -
int c = 0;
monAddition2( 1, 2, &c) 0xEC 1
} 0xF0 2
0xF4 0xD8
0xF8 0
57
Définition mémoire
void monAddition2( int a , int b , int* pc ){ 0xD0 -
int c = 0;
0xD4 -
c = a + b;
*pc = c; 0xD8 0
}
0xDC -
0xE0 -
Utilisation 0xE4 -
void main(){ 0xE8 -
int c = 0;
monAddition2( 1, 2, &c) 0xEC 1
} 0xF0 2
0xF4 0xD8
0xF8 3
58
Définition mémoire
void monAddition2( int a , int b , int* pc ){ 0xD0 -
int c = 0;
0xD4 -
c = a + b;
*pc = c; 0xD8 3
}
0xDC -
0xE0 -
Utilisation 0xE4 -
void main(){ 0xE8 -
int c = 0;
monAddition2( 1, 2, &c) 0xEC 1
} 0xF0 2
0xF4 0xD8
0xF8 3
59
Définition mémoire
void monAddition2( int a , int b , int* pc ){ 0xD0 -
int c = 0;
0xD4 -
c = a + b;
*pc = c; 0xD8 3
}
0xDC -
0xE0 -
Utilisation 0xE4 -
void main(){ 0xE8 -
int c = 0;
monAddition2( 1, 2, &c) 0xEC -
} 0xF0 -
0xF4 -
0xF8 -
60
Utilisation
void main(){
int a,b;
a = 2;
b = 3;
monEchange(&a,&b);
}
61
Commentaires
• Les fonctions permettent de sortir la valeur d'une seule variable
• L'instruction return(a,b)n'existe pas!!!!
62
Exercice 1
Ecrire une fonction en langage C nommée max qui renvoie la valeur max
de 2 entiers. Tester votre fonction dans un programme principale qui
affiche le résultat avec les valeurs 2 et 3
63
Exercice 2
64
65
LES TABLEAUX
66
Tableaux statiques
• Déclaration
float tab1[10];
unsigned int tab2[20], tab3[15];
• Initialisation
float tab1[10] = {1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0};
unsigned int tab2[20] = {1,4,5};
• Remarques
• Les indexes de tableau vont de 0 à N-1
• La taille du tableau doit être connue lors de la compilation
• ex
float tab3[n];
67
68
int tab[4];
tab[0] = 1;
tab[1] = 2;
tab[2] = 3;
tab[3] = 4;
69
adresse mémoire
tab tab[0]
tab+1 tab[1]
tab+2 tab[2]
tab+3 tab[3]
70
71
Allocation de mémoire
• Lors d'une allocation statique de mémoire
• La taille de la mémoire doit être une constante (connue lors de la
compilation)
• la mémoire est libérée implicitement en fin de fonction
72
Définition
float maMoyenne( float* tab, int n ){
int i = 0;
float acc = 0.0;
for(i = 0 ; i < n ; i++){
acc += tab[i];
}
return(acc/n);
}
Utilisation
void main(){
float moy = 0.0;
float tab[2] = {3.5 , 10.8}; Tableau statique
moy = maMoyenne( tab, 2);
}
73
74
Utilisation
void main(){
int n = 10; Tableau statique
int tab[10];
maSuite( tab, n);
}
75
Utilisation
76
Exercice
Ecrire une fonction en langage C nommée afficheTab qui affiche les
valeurs d’un tableau de taille arbitraire. Ecrire ensuite une fonction
nommée shiftTab qui décale les valeurs d’un tableau de taille arbitraire
vers la gauche et qui remplace la dernière valeur du tableau par 0.
Tester vos fonctions avec le tableau [1 2 3].
77
COMPLÉMENTS
78
Equivalences
• Directive #define
• Les équivalences sont remplacées par leur valeur par le pré-processeur
• Exemple :
79
Opérateur conditionnel
• Opérateur ?:
• Opérateur ternaire permettant de remplacer la structure if else
• Exemple :
int a, b, c;
...
c = a > b ? a : b; // if a>b "execute" a, else b
80
Enumération
• Mot clef enum
• Permet de créer un type dénombrable personnalisé
• Exemple :
/*déclaration de l'enumérateur*/
enum couleur_e {BLEU=0,BLANC=1, ROUGE=2};
81
Structures
• Déclaration de la structure
struct personne_s {
char prenom[20];
int age;
};
• Exemples d'utilisation
p1_s.age = 30;
p2_ps->age = 31;
82
Type personnalisé
• Le mot clef typedef permet de définir un nouveau type de donnée
• Exemples d'utilisation
83
int MA_VARIABLE;
void fonction(){
…
}
• Variables locales
• Déclarées dans une fonction
void fonction(){
int maVariable;
}
84
int maVariable_i;
• Classe statique
• La variable est stockée à une adresse fixe
static int maVariable_i;
• Classe "register"
• Spécifie au compilateur que la variable est utilisée souvent
• L'accès à cette variable est optimisée
85
float x = 3.14;
int a = (int)x
86
DU PROGRAMME À
L'EXÉCUTABLE
87
Pre- Linking
Compiling Assembling
processing
88
Code source
• Contient l'ensemble du code C du programme
#include <stdio.h>
int main(){
89
Etape 1 : Pre-processing
Pre- # 1 "bonjour.c"
processing # 1 "<interne>"
# 1 "<ligne de commande>"
# 1 "bonjour.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 28 "/usr/include/stdio.h" 3 4
bonjour.c bonjour.i # 1 "/usr/include/features.h" 1 3 4
# 329 "/usr/include/features.h" 3 4
• Operations de # 1 "/usr/include/sys/cdefs.h" 1 3 4
substitution dans le code …
extern int printf(__const char* __restrict
• #include, #if, _format,…);
#define ,/* */ …
• Contrôle de syntaxe # 2 "bonjour.c" 2
int main(){
90
Etape 2 : Compilation
.file "bonjour.c"
.section .rodata
Compiling .LC0:
.string "bonjour!!"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
bonjour.i bonjour.s andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
• Le code C est transformé pushl %ecx
subl $4, %esp
en code assembleur movl $.LC0, (%esp)
call puts
movl $0, %eax
>> gcc –s bonjour.i addl $4, %esp
popl %ecx
>> ls popl %ebp
bonjour.c bonjour.i bonjour.s leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20071124 (Red
Hat 4.1.2-42)"
.section .note.GNU-stack,"",@progbits
91
Etape 3 : Assembling
0000000 457f 464c 0101 0001 0000 0000 0000 0000
0000020 0001 0003 0001 0000 0000 0000 0000 0000
0000040 00ec 0000 0000 0000 0034 0000 0000 0028
Assembling 0000060 000b 0008 4c8d 0424 e483 fff0 fc71 8955
0000100 51e5 ec83 c704 2404 0000 0000 fce8 ffff
0000120 b8ff 0000 0000 c483 5904 8d5d fc61 00c3
0000140 6f62 6a6e 756f 2172 0021 4700 4343 203a
0000160 4728 554e 2029 2e34 2e31 2032 3032 3730
0000200 3131 3432 2820 6552 2064 6148 2074 2e34
bonjour.s bonjour.o 0000220 2e31 2d32 3234 0029 2e00 7973 746d 6261
0000240 2e00 7473 7472 6261 2e00 6873 7473 7472
0000260 6261 2e00 6572 2e6c 6574 7478 2e00 6164
0000300 6174 2e00 7362 0073 722e 646f 7461 0061
• Le code assembleur est 0000320 632e 6d6f 656d 746e 2e00 6f6e 6574 472e
transformé en code 0000340
0000360
554e
0000
732d
0000
6174
0000
6b63
0000
0000
0000
0000
0000
0000
0000
0000
0000
machine *
0000420 0000 0000 001f 0000 0001 0000 0006 0000
0000440 0000 0000 0034 0000 002b 0000 0000 0000
0000460 0000 0000 0004 0000 0000 0000 001b 0000
0000500 0009 0000 0000 0000 0000 0000 035c 0000
>> gcc –c bonjour.s 0000520 0010 0000 0009 0000 0001 0000 0004 0000
>> ls 0001340 0003 0003 0000 0000 0000 0000 0000 0000
bonjour.c bonjour.i bonjour.s 0001520 6961 006e 7570 7374 0000 0000 0014 0000
bonjour.o 0001540 0501 0000 0019 0000 0902 0000
0001554
92
Etape 4 : Linking
Linking
93
Compilation séparée
main.c func.c
#include "func.h" func.h #include "func.h"
main(){ int maFonction1(..); int maFonction1(..){
int x,y; float maFonction2(..); …
y = maFonction1(x); }
… float maFonction2(..){
} …
}
>> gcc –c main.c
>> gcc –c func.c
10110001
10011001 Preprocessing 10110001
01100011
main.o 10010100 + compiling + 10011001
01100011
10101010
01101010 assembling 10010100 func.o
10101010
0
01101010
0
main.x
94
Utilisation de bibliothèques
main.c
#include <math.h>
#include "func.h"
main(){
int x,y; Bibliothèques Bibliothèques
y = maFonction1(x); standard utilisateur
…
}
>> gcc –c main.c maths func
Preprocessing
10110001
+ compiling + func.a (statique)
10011001
main.o
01100011
10010100 assembling func.so (dynamique)
10101010
01101010
0
main.x
95