ITC34 - Algorithmique et programmation

publicité
ITC34 - Algorithmique
et programmation
Partie C / C++
Introduction
Petite introduction
Benoît DARTIES
1
[email protected]
2
Introduction
Introduction
Qu’est-ce que le C++ ?
Qu’est-ce que le C ?
‣ Langage de programmation impératif
- code écrit selon une suite d’instructions élémentaires
- quatre type d’instructions principales
➡ assignation
➡ branchement conditionnel
➡ branchement sans condition
➡ bouclage
- conçu pour la programmation système UNIX
ITC34 - Partie C / C++
3
Benoît Darties
‣ langage de programmation offrant de multiples paradigmes :
- programmation impérative
- programmation orientée objet
- programmation générique
- ...
‣ considéré comme le petit frère du C
‣ apporte de nouveaux éléments par rapport au C
- objets
- fonctions virtuelles
- surcharge des opérateurs et des fonctions
- références
- gestion de flux d’entrée / sortie
- ...
ITC34 - Partie C / C++
Histoire du langage C
Benoît Darties
Histoire du langage C
1989, Ratification du standard : ANSI X3.159-1989
1972, Naissance du C
‣ ANSI C, Standard C ou encore C89
‣ Développé par Dennis M. Ritchie, laboratoire Bell
‣ Objectif : développer une version portable d’UNIX
‣ Inspiré du langage B (1970, Ken Tompson)
1990, Adoption par l’ISO du standard ANSI
‣ International Organisation for Standardization
‣ Norme ISO/IEC 9899:1990
‣ C90 (identique C89)
1978, définition officielle
‣ par Brian W. Kernighan & Dennis M. Ritchie
‣ livre «The C programming language», le K&R-C
1999 : Révision du standard
1983 : nouveau standard
‣ besoin d’une référence, pour répondre aux problèmes de compatibilité
‣ Standardisation ANSI-C (Américan National Standards Institute)
‣ Publication dans la seconde édition du K&R-C (1988)
ITC34 - Partie C / C++
4
5
Benoît Darties
‣ Norme ISO/IEC 9899:1990
‣ C99
‣ Ajout des fonctions inline, types de données, ...
2007 : réflexions sur une évolution du standard : C1X
ITC34 - Partie C / C++
6
Benoît Darties
Histoire du langage C++
Histoire du langage C++
1985, première référence
1979, Pendant ce temps ...
‣ livre «The C++ programming language»
‣ pas encore de standard officiel
‣ Bjarne Stroustrup travaille sur l’ajout de classes au C
- encapsulation de données
- classes dérivées
- typage fort
- fonctions inline (repris dans C)
1989, seconde version de C++
‣ héritage multiple
‣ classes abstraites
‣ ...
1983, C++ adopté comme nom officiel
‣ ajout de fonctionnalités supplémentaires
- fonctions virtuelles
- surcharge d’opérateurs
- références
- constantes (repris dans C)
- commentaires de fin de lignes // (repris dans C)
- ...
ITC34 - Partie C / C++
1990, «The annotated C++ Reference Manual» (ARM)
‣ bases pour le futur standard
1998, Standardisation (ISO/CEI 14882:1998)
‣ Version corrigée en 2003 (ISO/CEI 14882:2003)
Benoît Darties
7
Popularité des langages de programmation
Position
Aug 2009
Delta in Position
1
1
=
Java
17.994%
-1.53%
A
2
2
=
C
17.866%
+0.65%
A
3
3
=
C++
9.658%
-0.84%
A
4
4
=
PHP
9.180%
-0.21%
A
5
5
=
(Visual) Basic
5.413%
-3.07%
A
6
7
+
C#
4.986%
+0.54%
A
7
6
-
Python
4.223%
-0.27%
A
8
8
=
Perl
3.427%
-0.60%
A
9
19
++++++++++
Objective-C
3.150%
+2.54%
A
10
11
+
Delphi
2.428%
+0.09%
A
11
9
--
JavaScript
2.401%
-0.41%
A
12
10
--
Ruby
1.979%
-0.51%
A
13
12
-
PL/SQL
0.757%
-0.23%
A
14
13
-
SAS
0.715%
-0.10%
A
15
20
+++++
MATLAB
0.627%
+0.07%
B
16
18
++
Lisp/Scheme/
0.626%
0.00%
B
17
16
-
Pascal
0.622%
-0.05%
B
18
15
---
ABAP
0.616%
-0.12%
B
19
14
-----
RPG (OS/400)
0.606%
-0.15%
B
20
-
++++++++++
Go
0.603%
0.00%
B
ITC34 - Partie C / C++
Jul 2010
/ Jul 2009
9
8
Benoît Darties
Popularité des langages de programmation
Position
Aug 2010
Lanugage
ITC34 - Partie C / C++
Status
Benoît Darties
ITC34 - Partie C / C++
Ne pas confondre C et C++ !
10
Benoît Darties
Organisation de ce cours
Partie C
Langages très proches
‣ s’inspirent mutuellement
‣ fortes interactions :
- Compilation d’un programme C avec un compilateur C++
- Utilisation de librairies statiques développées en C++ dans du C
- ...
‣ mais doivent être considérés comme des langages séparés !
ITC34 - Partie C / C++
11
Benoît Darties
‣ Bases du langage
‣ Compilation
‣ Gestion de la mémoire
- mise en application sur le langage C
- fonctionnement étendu au C++ (non présenté)
Partie C++
‣ Ajouts / modifications en langage impératif par rapport au C++
- Surcharge de fonctions, d’opérateurs ..
- Gestion des flux
‣ Programmation orientée objets
‣ Librairies C++
ITC34 - Partie C / C++
12
Benoît Darties
Composition du langage C
Six groupes de composants élémentaires :
les identificateurs
les mots-clé
les constantes
les chaînes de caractères
les opérateurs
les signes de ponctuation
(éventuellement les commentaires)
Bases du langage C
ITC34 - Partie C / C++
13
Benoît Darties
14
Les identificateurs
Les mots-clé
Rôle d’un identificateur
‣ Donner un rôle à une entité du programme
‣ Peut désigner :
- un nom de variable
- un nom de fonction
- un type
- ....
mots réservés pour le langage C
‣ ne peuvent être utilisés comme identificateurs
‣ ANSI C compte 32 mots-clé
‣ différentes utilités
Composition : suite de caractères
‣
‣
‣
‣
‣
lettres majuscules / minuscules non accentuées
chiffres
caractère «underscore» _
ne peut commencer par un chiffre
respect de la casse : différenciation des majuscules / minuscules
ITC34 - Partie C / C++
15
Benoît Darties
auto
const
double
float
int
short
struct
unsigned
break
continue
else
for
long
signed
switch
void
case
default
enum
goto
register
sizeof
typedef
volatile
char
do
extern
if
return
static
union
while
ITC34 - Partie C / C++
Structure d’un programme C
16
Benoît Darties
Structure d’un programme C
Un programme C :
‣
‣
‣
‣
manipule des variables
nommées par un identificateur
sur lesquelles il effectue des opérations utilisant des opérateurs
ces opérations sont décrites par des instructions
‣ suite d’instructions encadrée par des crochets ouvrant et fermant
‣ inclusion des blocs d’instructions possible
Une variable :
Une instruction :
‣ est une expression : suite de composants syntaxiquement correct
‣ suivie d’un point virgule
‣ a pour objet le résultat d’une action décrite par l’expression
- affectation : associer une valeur à un variable
- comparaison : comparaison de valeurs
- opération mathématique ou logique : calcul d’une valeur
- branchement : saut vers une instruction non consécutive
- ...
ITC34 - Partie C / C++
bloc d’instruction :
17
Benoît Darties
‣
‣
‣
‣
espace mémoire fini
identifiée par un identificateur
capable de contenir une valeur
possède un type : int, float, char, ...
- nécessite d’être déclarée avant utilisation
‣ portée généralement limitée au bloc d’instruction dans lequel elle est
définie
ITC34 - Partie C / C++
18
Benoît Darties
Structure d’un programme C
Types de données
Squelette d’un programme C
Types de données
[directives du préprocesseur]
‣ Le langage C est un langage typé
‣ toute variable, fonction, constante est typée
‣ Un type définit :
- la façon dont l’élément est représenté en mémoire
- la taille occupée par l’élément
- les valeurs que peut prendre l’élément (=domaine)
- les opérations autorisées sur ce dernier
‣ Deux familles de types :
- type primitifs
- types composés (abordés plus loin)
[déclaration de variables externes]
[fonctions secondaires]
int main() {
// bloc d’instructions du main
[variables internes]
[instructions]
}
ITC34 - Partie C / C++
Benoît Darties
19
ITC34 - Partie C / C++
Types de données
20
Benoît Darties
Représentation des caractères
Relation entre type, taille, encodage, signification
Types représentant les caractères
‣ espace mémoire de taille n bits : mot binaire
Bit de poids le + fort
1 0 1 0 1 0 0 1 1 0 0 1 0 0 1 0
Bit de poids le + faible
‣ 2^n mot binaires possibles, chacun représente une valeur
valeur binaire sur espace mémoire taille 16 bits
valeur décimale
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
3
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
...
0 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1
26055
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
...
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
65535
Signification
Dépend du type !
entier ?
valeur négative ?
réel ?
caractère ?
mot ?
autre ?
‣
‣
‣
‣
utilisés pour représenter des caractères
mot clé : char
objet élémentaire du langage C
taille : 1 octet (la plupart du temps), soit 256 possibilités
- chaque valeur est associée à un caractère
- correspondance selon le jeu de caractères de la machine utilisée
➡ Généralement jeu de caractères ISO 8859 (8 bits)
➡ Valeurs 0 à 127 : table ASCII (codée sur 7 bits)
➡ Valeurs 128 à 255 : caractères propre aux différentes langues
➡ En Europe occidentale : ISO 8859-1 (ISO-LATIN-1)
‣ une variable de type char est un mot binaire d’un octet auquel est
associé un caractère ! (par l'intermédiaire d’une valeur décimale)
taille : dépend du type utilisé
ITC34 - Partie C / C++
21
Benoît Darties
ITC34 - Partie C / C++
Représentation des entiers
Attribut de précision :
‣ utilisés pour représenter des valeurs entières
- on ne peut pas représenter tous les entiers !
- impossible de représenter tous les éléments d’une quantité infinie
‣ mot clé : int
- peut-être précédé d’un attribut de précision : short ou long
- et/ou d’un attribut de représentation : unsigned
‣ mot clé : char
- peut être précédé d’un attribut de représentation : unsigned
23
Benoît Darties
Représentation des entiers
Types représentant les entiers
ITC34 - Partie C / C++
22
Benoît Darties
‣ short, long , (long long depuis C99, non ANSI)
‣ Modifie le nombre d’octets alloués à la variable
Encodage du signe des entiers :
‣ bit de poids le plus fort à 0 pour les entiers positifs
‣ attribut unsigned
- utilisation du bit de poids le plus fort pour l’encodage du nombre
- encodage d’entiers positifs ou nul seulement
- valeur max deux fois plus grande
ITC34 - Partie C / C++
24
Benoît Darties
Représentation des entiers
Représentation des entiers
Tableau des types de données pour entiers (C99, proc. 32 bits)
Type
Signification
Taille (octet)
Plage de valeurs
char
Caractère
1
unsigned char
Caractère non signé
1
0 à 255
short int
Entier court
2
-32768 à 32767
unsigned short int
Entier court non signé
2
int
Entier
4
unsigned int
Entier non signé
4
long int
unsigned long int
Entier long
Entier long non signé
4
2
long long int
Entier long long
8
unsigned long long int Entier long long non signé
ITC34 - Partie C / C++
8
-128 à 127
0 à 65535
-32768 à 32767
-2147483648 à 2147483647
0 à 65535
0 à 4294967295
-2 147 483 648 à 2 147 483 647
0 à 4 294 967 295
–9,223,372,036,854,775,808 à
9,223,372,036,854,775,807
0 à 18,446,744,073,709,551,615
Benoît Darties
25
Conséquences :
entier a;
debut
a <- 1;
tant que (a > 0) faire
a<- a + 1;
fin tant que
fin
int main() {
int a;
a=1;
while (a > 0) {
a = a+1;
}
}
Algorithme de boucle infinie
Implémentation en C
‣ L’algorithme ne s’arrête jamais (exécution infinie)
‣ Le programme s’arrêtera au bout d’un certain temps
- ceci quel que soit le type de la variable a
- type : retarde la fin d’exécution
ITC34 - Partie C / C++
Représentation des entiers
Benoît Darties
26
Représentation des entiers
Incrémentation d’une variable dont la valeur est maximum
‣ Integer Overflow
‣ Résultat obtenu dépendant du type (donc de la représentation)
- Type non signé (mot clé unsigned )
- Type signé
- Problèmes dans tous les cas
Exemple : pacman
‣
‣
‣
‣
‣
‣
‣
‣
‣
Benoît Darties
27
Représentation des entiers négatifs
Approche naïve : méthode Sign-and-Magnitude
Décimal
Binaire
Décimal
00000000
0
10000000
-0
00000101
5
10000101
-5
01000001
65
11000001
-65
01111111
127
11111111
-127
Représentation sur type de taille 1 octet
‣ Inconvénients :
- double représentation du 0
- opérations arithmétiques compliquées
29
ITC34 - Partie C / C++
Benoît Darties
28
Représentation des entiers négatifs
‣ Nombre positif codé sur n-1 bits
‣ Pour obtenir le négatif : inversion des bits
Binaire
ITC34 - Partie C / C++
Bit de poids fort à 0 pour les entiers positifs
Valeur Max atteinte lorsque représentation binaire : 0111...1111
Valeur numérique de 1000...0000 jusqu’à 1111...1111 ?
Comment sont représentés les entiers négatifs ???
Pourquoi peut-on représenter un négatif de plus qu’un positif ??
Complément-à-un
‣ n-1 bits de poids faibles : code un nombre
‣ 1 bit de poids le plus fort : code le signe
- 0 : nombre positif
- 1 : nombre négatif
Représentation sur type de taille 1 octet
‣ Le poids de chaque bit correspond à une puissance de deux
‣ Valeur max atteinte lorsque représentation binaire : 1111...1111
‣ incrémentation : 10000 ... 0000
- bit tout à gauche inexistant
- réduction au nombre 0000...0000
Représentation des valeurs entières sur type signé
Numéro de level codé sur 1 octet
256 possibilités
Levels 0 à 255 OK
Level 256 : problèmes d’affichage
ITC34 - Partie C / C++
Représentation des valeurs entières sur type non signé :
Benoît Darties
Binaire
Décimal
Binaire
Décimal
00000000
0
11111111
-0
00000101
5
11111010
-5
01000001
65
10111110
-65
01111111
127
10000000
-127
Représentation sur type de taille 1 octet
Représentation sur type de taille 1 octet
‣ Avantages :
- certaines opérations mathématiques sont facilités
- exemple : addition
‣ Inconvénients :
- double représentation du 0
ITC34 - Partie C / C++
30
Benoît Darties
Représentation des entiers négatifs
Représentation des entiers négatifs
Complément-à-deux
Excess-N
‣ Nombre positif codé sur n-1 bits
‣ Pour obtenir le négatif : inversion des bits, et ajout de 1
‣ Représentation d’un entier en mode non signé.
‣ Soustraction de la valeur N
Binaire
Décimal
Binaire
Décimal
00000000
0
00000000
-0
00000101
5
11111011
-5
Binaire
Décimal
Binaire
Décimal
01000001
65
10111111
-65
00000000
-127
10000000
1
01111111
127
10000001
-127
00000101
-126
11111011
2
01000001
-1
10111111
127
01111111
0
10000001
128
Représentation sur type de taille 1 octet
‣ Exemple : Excess-127 sur 8 bits
Représentation sur type de taille 1 octet
‣ Avantages :
- certaines opérations mathématiques sont facilités
- exemple : addition
- représentation unique du 0
ITC34 - Partie C / C++
Représentation sur type de taille 1 octet
‣ Avantages :
- certaines opérations mathématiques sont facilités
- représentation unique du 0
Benoît Darties
31
ITC34 - Partie C / C++
Représentation des réels
Benoît Darties
Représentation des nombres flottants :
On ne peut représenter tous les nombres réels
Approximation des nombres ET des opérations
Norme IEEE 754
Types float, double, long double
‣ Elements utilisés :
- un signe S : 0 ou 1
- un exposant E
- une mantisse M
- deux constantes Exp1 et Exp2
Quelques caractéristiques :
‣ Zero positif et négatif
‣ Valeur spéciale :
- NaN : Not A Number
- Positive et Negative Infinite
‣ Toutes les valeurs entières représentées dans l’intervalle de définition
‣ Résultats des opérations : peut être approximatif
ITC34 - Partie C / C++
32
Représentation des réels
Représentation des nombres réels
‣
‣
‣
‣
Représentation sur type de taille 1 octet
Benoît Darties
33
Représentation des entiers
(-1)^S x 1.M x 2^(E - Exp1)
‣ Nombres normalisés :
‣ Nombres dénormalisés (E=0) : (-1)^S x 0.M x 2^(E - Exp2)
ITC34 - Partie C / C++
34
Benoît Darties
Les constantes et chaînes de caractères
Tableau des types de données pour flottants
Taille
(octets)
Mantisse
(bits)
Exposant
(bits)
Exp1
Exp2
float
4
23
8
127
126
3.4*10^-38 à 3.4*10^38
double
8
52
11
1023
1022
1.7*10^-308 à 1.7*10^308
long double
10
64
15
16283
16382
3.4*10^-4932 à 3.4*10^4932
Type
Plage de valeurs
Arithmétique des flottants
-00
0
ITC34 - Partie C / C++
0
1
+00
35
1
Benoît Darties
Les constantes
‣ valeurs qui apparaissent littéralement dans un code source
‣ différents types :
- constantes représentant une valeur entière
- constantes représentant une valeur réelle
- constante représentant un caractère
- constante représentant une chaîne de caractères
- ...
‣ Manière dont est écrite une constante : détermine son type.
‣ Si ambiguïtés : type par défaut
ITC34 - Partie C / C++
36
Benoît Darties
Opérateurs
Opérateurs
Les opérateurs :
‣ définissent des opérations à effectuer sur des opérandes
- opérateurs unaires : une opérande
- opérateurs binaires : deux opérandes
Types d’opérateurs :
‣
‣
‣
‣
‣
‣
‣
‣
Opérateurs de calcul
Opérateurs d’affectation
Opérateurs d’incrémentation
Opérateurs de comparaison
Opérateurs logiques
Opérateurs bit-à-bit
Opérateurs de rotation de bits
Liste des opérateurs : cf internet / cours shell (syntaxe proche)
ITC34 - Partie C / C++
37
Benoît Darties
Manipulation:
‣ définis en conjonction avec le type des opérandes utilisés
‣ opérateurs binaires sur même types de données
‣ liste de tous les opérateurs : cf cours shell / internet
Définitions multiples :
‣ exemple pour l’opérateur +
- [int] + [int] : renvoie un int
- [float] + [float] : renvoie un flottant
‣ Que se passe-t’il si l’on additionne un int avec un float ?
ITC34 - Partie C / C++
Transtypage
L’opérateur sizeof
Opérateur sizeof
Définition du transtypage
‣ faculté de convertir une variable d’un type donné en un autre type
‣ transtypage implicite : déduit logiquement du contexte
- exemple : [int] + [float]
- la valeur [int] est interprétée comme un flottants
- opération réduite à [float] + [float] : retourne un flottant
‣ transtypage explicite : précisé par le programmeur
- précision du type à convertir entre parenthèses avant la variable
- lève les ambigüités et les restrictions de certains compilateurs
- interpréter comme on le souhaite n’importe quelle zone mémoire
- exemple : (float) [int] + (float) [int]
- les valeurs [int] sont interprétées comme des flottants
- opération réduite à [float] + [float] : retourne un flottant
ITC34 - Partie C / C++
Benoît Darties
38
39
Benoît Darties
‣ Renvoie le nombre d’octets utilisée par :
- une variable, qu’elle soit initialisée ou non
- un type primitif ou composé
‣ Défini en tant que pseudo-opérateur, s’utilise comme une fonction
‣ Permet d’ajouter une couche d’abstraction
int main() {
int a;
struct sockaddr_in b;
char c;
a
a
a
a
a
= sizeof ( int );
= a + sizeof ( a );
+= sizeof ( c );
-= sizeof ( b );
*= sizeof (struct sockaddr_in) ;
ITC34 - Partie C / C++
Structures itératives non déterministes
while (...) {...} : itérations pré-conditionnées
while ( test ) {
// instructions réalisées tant que le test est vrai
...
}
//
//
//
//
//
affecte valeur 4
ajout valeur 4
ajout valeur 1
soustrait valeur 16
multiplie valeur 16
40
Benoît Darties
Structures conditionnelles
if (...) then { ...} else {...}
if ( test ) {
// suite d’instructions si le test est valide
}
else {
// suite d’instruction si le test est invalide
}
do {...} while (...) : itérations post-conditionnées
do {
// instructions réalisées tant que le test est vrai
// chaque instruction est réalisée au moins une fois
...
} while ( test );
ITC34 - Partie C / C++
41
Benoît Darties
(...) ? ... : ... ;
( test ) ? instruction test OK : instruction si test !OK ;
ITC34 - Partie C / C++
42
Benoît Darties
Structures conditionnelles
Structures itératives
switch ( ... ) { case ... case ... case ...}
switch (variable à tester ) {
case valeur1 :
...
break;
// instructions si variable = valeur1;
// fin d’instructions!
// Sinon poursuite des instructions
case valeur2 :
...
break;
// instructions si variable = valeur2;
default :
...
// instructions dans tout autre cas
// fin d’instructions!
// Sinon poursuite des instructions
Itérations déterministes : for ( ... ; ... ; ...) { ... }
for ( affectation d’une variable; test ; incrémentation) {
// instructions réalisées tant que le test est vrai
...
}
}
ITC34 - Partie C / C++
43
Benoît Darties
ITC34 - Partie C / C++
Fonctions et procédures
Fonctions et procédures
Ensemble d’instructions groupées dans un bloc :
‣ Possèdent un identifiant
‣ Paramètres passés entre parenthèses, séparés par une virgule
- données
- résultats
- données / résultats
‣ Valeur retour ?
- une fonction retourne un résultat :
➡ nécessite un type
➡ valeur retournée du type défini
➡ possibilité de transtypage
- une procédure n’en retourne pas.
➡ type void
ITC34 - Partie C / C++
45
Appel d’une fonction / procédure
‣ nom de la fonction / procédure suivi de la liste de ses paramètres
‣ exécution déroutée pour exécuter les instructions du bloc de fonction
‣ en fin d’exécution, retour au point de branchement, exécution des
instructions suivantes
‣ Empilement de fonctions possibles
Conditions nécessaires à l’appel d’une fonction
‣ le compilateur doit connaître l’utilisation de cette fonction
- nom (identificateur)
- paramètre(s) ?
- valeur retour ?
Benoît Darties
ITC34 - Partie C / C++
Fonctions et procédures
Etude d’un exemple :
‣ Signature : Permet d’identifier la fonction de manière unique
‣ Prototype : annonce la façon d’utiliser une fonction
‣ Déclaration : suite des instructions
Lors d’un appel de fonction dans un programme :
‣ le prototype doit être connu
- fichiers en-têtes .h
- annonce du prototype avant l’appel
‣ si la fonction est déclarée avant l’appel : pas de problème
‣ appel sans déclaration préalable :
- le compilateur suppose une déclaration post-appel
- attribution d’un prototype par défaut (avec type int)
- si prototype supposé différent de la déclaration : erreur !
47
Benoît Darties
46
Fonctions et procédures
Elements caractérisant les fonctions :
ITC34 - Partie C / C++
Benoît Darties
44
Benoît Darties
paramètres
int addition(int v1, int v2)
return v1 + v2 ;
}
int main() {
int a;
int b = 6;
a = addition(5, b);
{
mot clé return
Appel en précisant les
valeurs de paramètres
}
Appel OK car fonction
précédemment déclarée
ITC34 - Partie C / C++
48
Benoît Darties
Fonctions et procédures
Fonctions et procédures
Etude d’un exemple :
Etude d’un exemple :
Lecture de haut en bas :
Appel d’une fonction
inconnue. Type supposé :
int addition(int, int)
int main() {
int a;
int b = 6;
a = addition(5, b);
}
Avertissement : affectation d’un
float avec un int
int addition(int v1, int v2)
return v1 + v2 ;
}
ITC34 - Partie C / C++
{
La déclaration colle avec le
prototype supposé :
compilation et exécution OK
Benoît Darties
49
float addition(float v1, float v2)
return v1 + v2 ;
}
{
La déclaration ne
colle pas avec le
prototype supposé
int addition(float, float) introuvable
ITC34 - Partie C / C++
Fonctions et procédures
Benoît Darties
50
Fonctions et procédures
Etude d’un exemple :
Etude d’un exemple :
float addition(float , float );
int main() {
float a;
float b = 6.0;
a = addition(5.0, b);
}
prototype annoncé
prototype annoncé
float addition(float , float );
Lecture de haut en bas :
Appel d’une fonction
float addition(float, float)
float addition(float v1, float v2)
return v1 + v2 ;
}
ITC34 - Partie C / C++
Lecture de haut en bas :
Appel d’une fonction
inconnue. Type supposé :
int addition(float, float)
int main() {
float a;
float b = 6.0;
a = addition(5.0, b);
}
{
déclaration de la fonction
float addition(float, float) introuvable.
Erreur à la compilation
déclaration de la fonction
float addition(float, float)
Benoît Darties
51
Lecture de haut en bas :
Appel d’une fonction
float addition(float, float)
int main() {
float a;
float b = 6.0;
a = addition(5.0, b);
}
ITC34 - Partie C / C++
52
Benoît Darties
Fonctions et procédures
Etude d’un exemple :
float addition(float , float );
int main() {
float a;
float b = 6.0;
a = addition(5.0, b);
}
prototype annoncé
Lecture de haut en bas :
Appel d’une fonction
float addition(float, float)
int addition(float v1, float v2) {
return v1 + v2 ;
Ne colle
}
pas avec le prototype.
Identificateur de fonctions déja
réservé . Conflit de signature !!!
ITC34 - Partie C / C++
53
Benoît Darties
Compilation d’un programme
54
Compilation de code
Compilation de code
Compilateurs de référence :
Objectif de la compilation :
‣ Traduire un code source (fichier ASCII écrit par un utilisateur) en un
code cible (fichier binaire) directement interprétable par le processeur
‣ Nécessité d’un compilateur
Le compilateur :
‣ programme informatique
‣ traduit le code source en code cible
‣ généralement :
- code source écrit en langage de programmation
- code cible résultant en langage assembleur ou en langage machine
ITC34 - Partie C / C++
Benoît Darties
55
‣ pour le langage C : gcc
‣ pour le langage C++ : g++
‣ pour le langage JAVA : javac
Ex : compiler un programme C avec gcc
‣ gcc fichierSource.c -o fichierCible
‣ production du code fichierCible à partir du code fichierSource.c
‣ Simple et efficace ... jusqu’à un certain point ...
gcc
code
source
.c
ITC34 - Partie C / C++
Compilation de code
‣ lecture du code source
‣ interprétation des directives de précompilation
- définies dans le code source par une ligne commençant par #
- #include, #define, #ifndef, #endif ...
‣ remplacement par la valeur associée dans le code source
‣ production de code source enrichi
‣ visualiser le code source enrichi sur stdout avec gcc : option -E
compilateur
code
source
enrichi
code
source
ITC34 - Partie C / C++
Benoît Darties
Fonctionnement du préprocesseur
Préprocesseur
Compilateur
Assembleur
Edition de lien
préprocesseur
56
Rôle du préprocesseur
Etapes de la compilation d’un fichier sous gcc :
‣
‣
‣
‣
code
exécutable
assembleur
code
assembleur
57
Exemple : directives #include <...> et #include "..."
Edition de liens
code
objet
code
exécutable
Benoît Darties
‣ ligne remplacée par le contenu du fichier header correspondant
- #include <fichier.h> : recherche fichier.h dans le répertoire usuel
- #include "fichier.h" : recherche fichier.h dans le répertoire courant
ITC34 - Partie C / C++
Rôle du compilateur
58
Benoît Darties
Rôle du compilateur
1. analyse lexicale
‣ élimination du bruit :
- commentaires /* .. */ ou //
- espaces redondants
‣ découpage du texte en petits mots
‣ reconnaissance des mots-clés et des opérateurs
‣ identification des variables
- utilisation d’une table des symboles
- correspondance identifiant / nom de variable
‣ génération de jetons (token)
- unités lexicales ou lexèmes
- mots clés, identifiants ...
Fonctionnement du compilateur
‣
‣
‣
‣
‣
lecture du code source enrichi
analyse du code (vision logique) :
1. analyse lexicale
2. analyse syntaxique
3. analyse sémantique
génération de code intermédiaire
optimisation du code
génération du code objet
ITC34 - Partie C / C++
59
Benoît Darties
ITC34 - Partie C / C++
60
Benoît Darties
Rôle du compilateur
Rôle du compilateur
1. analyse lexicale
int
main
(
int
=
b
=
if
a
5
=
a
(
1. analyse lexicale
{
a
int
c
)
8
+
c
=
;
,
c
(
>
2099
0
;
245
c
=
a
+
(
245
*
b
)
;
c
=
a
+
(
245
*
b
)
;
id(3)
aff
id(1)
add
ob
mul
id(2)
cb eol
Table des symboles
pos
*
)
b
)
;
{
nom
1
a
...
2
b
...
3
c
...
;
nbr(245)
}
}
ITC34 - Partie C / C++
61
Benoît Darties
ITC34 - Partie C / C++
Rôle du compilateur
Benoît Darties
62
Rôle du compilateur
2. analyse syntaxique
c
=
a
+
(
id(3)
aff
id(1)
add
ob
245
*
b
)
;
mul
id(2)
cb eol
Table des symboles
2. analyse syntaxique
‣ rôle : identifier la structure syntaxique du programme
‣ Conversion de la suite de lexème en arbre syntaxique
‣ Représentation des relations entre les lexèmes
pos
nom
1
a
...
2
b
...
3
c
...
nbr(245)
aff
id(3)
add
id(1)
mul
nbr(245)
ITC34 - Partie C / C++
63
Benoît Darties
ITC34 - Partie C / C++
Rôle du compilateur
id(2)
Benoît Darties
64
Rôle du compilateur
Génération de code intermédiaire
‣ code interne au compilateur
‣ encore très proche du code utilisateur
3. analyse sémantique
‣ Ajout des informations sémantiques sur l’arbre syntaxique
‣ Vérification de type
‣ Vérification de la conformité des opérateurs
- pas de comparaisons entre types incomparables
- pas d’affectation non autorisées
- ...
‣ Vérification de la validité de l’appel à une fonction (prototype présent)
Optimisation du code
‣ rendre le programme plus rapide
‣ garder des délais de compilation raisonnables
Code non optimisé
Code optimisé
tmp1 te<- EntVersRéel(60)
tmp2 <- mulRéel(id(3), tmp1)
tmp3 <- addRéel(id(2), tmp2)
id(1) <- tmp3
tmp1 <- mulRéel(id(3), 60.0)
id(1) <- addRéel(id(2), tmp1)
Création du code assembleur
ITC34 - Partie C / C++
65
Benoît Darties
ITC34 - Partie C / C++
66
Benoît Darties
Rôle du compilateur
Rôle de l’assembleur
Exemple de code assembleur
Traduction code assembleur en code machine
.text
.globl _main
_main:
LFB2:
!
pushq! %rbp
LCFI0:
!
movq!
%rsp, %rbp
LCFI1:
!
movl!
$50, -4(%rbp)
!
cmpl!
$40, -4(%rbp)
!
jne!L2
!
movl!
$30, -8(%rbp)
!
jmp!L6
L2:
!
movl!
$500, -8(%rbp)
L6:
!
leave
!
ret
int main() {
int a=50;
int b;
if (a==40) {
b = 30;
}
else {
b = 500;
}
}
ITC34 - Partie C / C++
67
Benoît Darties
.text
.globl _main
_main:
LFB2:
!
pushq! %rbp
LCFI0:
!
movq!
%rsp, %rbp
LCFI1:
!
movl!
$50, -4(%rbp)
!
cmpl!
$40, -4(%rbp)
!
jne!L2
!
movl!
$30, -8(%rbp)
!
jmp!L6
L2:
!
movl!
$500, -8(%rbp)
L6:
!
leave
!
ret
ITC34 - Partie C / C++
L’édition de liens
Programme et fonctions externes :
Deux types de librairies :
‣ Un programme utilise des éléments déjà existants :
- fonctions standard : main(), printf() ...
- appels systèmes
- ...
‣ Eléments «annoncés» dans le code source :
- déclaration de prototypes de fonctions
- utilisation de fichiers headers (.h), par exemple stdio.h
‣ La déclaration des fonctions utilisées n’est pas dans le code machine
qui a été compilé jusqu’à présent
‣ librairies statiques
‣ librairies dynamiques
Librairies statiques
‣ Extension .a sous UNIX
‣ Associées à l’exécutable généré
‣ Avantage :
- Tout est inclus : pas de problème de dépendance
- distribution de l’application facilitée
‣ Inconvénients :
- exécutable relativement lourd
- si modification : recompilation de la librairie ET de l’exécutable
Intérêt de l’édition de lien :
‣ Lien entre le code machine et le code des fonctions externes
‣ Réutilisation des fonctions précédemment développées
69
Benoît Darties
68
L’édition de liens
ITC34 - Partie C / C++
0000000 cf fa ed fe 07 00 00
01 03 00 00 00 01 00 00 00
0000010 03 00 00 00 50 01 00
00 00 20 00 00 00 00 00 00
0000020 19 00 00 00 e8 00 00
00 00 00 00 00 00 00 00 00
0000030 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00
0000040 70 00 00 00 00 00 00
00 70 01 00 00 00 00 00 00
0000050 70 00 00 00 00 00 00
00 07 00 00 00 07 00 00 00
0000060 02 00 00 00 00 00 00
00 5f 5f 74 65 78 74 00 00
0000070 00 00 00 00 00 00 00
00 5f 5f 54 45 58 54 00 00
Benoît Darties
ITC34 - Partie C / C++
L’édition de liens
Benoît Darties
70
Récapitulatif : compilation via gcc
gcc et options
Librairie dynamique
‣ Extension .so sous UNIX, .dylib sous MacOS X
‣ Associées au processus durant son exécution, quand nécessaire
‣ Avantage :
- Exécutable distribué plus léger
- Chargée une seule fois en mémoire, meme si utilisée par plusieurs
exécutables
- Si modification de la librairie (hors prototype), l’exécutable n’a
pas besoin d’être recompilé
‣ Inconvénients :
- problème de dépendances
- librairies non conformes sur autres systèmes
- versions de librairies
- temps de lancement plus long
ITC34 - Partie C / C++
71
Benoît Darties
préprocesseur
code
source
.c
compilateur
code
source
enrichi
assembleur
code
assembleur
Edition de liens
code
objet
code
exécutable
gcc -E
gcc -S
gcc -c
gcc
ITC34 - Partie C / C++
72
Benoît Darties
Récapitulatif : compilation via gcc
Compilation sur plusieurs fichiers
‣ code source dispatché sur plusieurs fichiers
‣ compilation séparé de chaque fichier jusqu’au code objet
‣ mise en relation lors de l’édition de liens
compilateur
assembleur
iti
Ed
préprocesseur
on
de
code
objet 1
préprocesseur
compilateur
code
code
source
source
.c
enrichi
ITC34 - Partie C / C++
Ed
i ti
on
de
lie
ns
code
assembleur
ns
code
source
enrichi
lie
code
source
.c
assembleur
code
assembleur
code
exécutable
Types complexes :
structures, tableaux
code
objet 2
73
Benoît Darties
74
Les structures
Les structures
Structure de données
Structures de données
‣ Groupe (encapsulation) de variables : type complexe
‣ formé à partir :
- de types simples
- de types complexes précédemment définis
// déclaration du type
struct date {
char jour;
//
char mois;
//
short int annee; //
};
//
Déclaration d’une structure
‣ mot clé struct
‣ liste des variables encapsulées entre accolades
- type suivi d’un identificateur
‣ identificateur à la structure
}
Benoît Darties
ITC34 - Partie C / C++
Les structures
Benoît Darties
Structures et opérateur sizeof
// déclaration du type personne
struct personne {
char age;
// entier de 0 à 150
struct date dateNaiss; // structure de type date
};
int main () {
struct personne Bobby;
‣
‣
‣
‣
Retourne la somme des types composant la structure
Besoin de connaître la taille des types avant de réserver la mémoire
Taille connue au terme de la déclaration de la structure
impossible de déclarer une structure dont la taille d’une des
composantes n’est pas connue :
// déclaration du type
struct dateImbriquee {
char jour;
//
char mois;
//
short int annee; //
struct dateImbriquee
};
Bobby.age = 29;
Bobby.dateNaiss.jour = 17;
Bobby.dateNaiss..mois = 7;
Bobby.dateNaiss..annee = 1981;
}
77
76
Les structures
Structure de données imbriquées
ITC34 - Partie C / C++
de 1 à 31
de 1 à 12
entre 0 et 9999
oublier le point-virgule
uneDate.jour = 25;
uneDate.mois = 12;
uneDate.annee = 2010;
‣ ident_structure.ident_variable
75
entier
entier
entier
ne pas
// manipulation
int main () {
struct date uneDate;
Accès aux éléments de la structure :
ITC34 - Partie C / C++
date
Benoît Darties
ITC34 - Partie C / C++
dateImbriquee
entier de 1 à 31
entier de 1 à 12
entier entre 0 et 9999
autreDate; // impossible !!
78
Benoît Darties
Les structures
Les tableaux
Tableau : structure de données
Structures et système
‣
‣
‣
‣
de nombreuses structures sont pré-définies dans le système
utilisées pour récupération de données systèmes
déclaration présente dans les fichiers en-têtes (extensions .h)
fonctions et appels systèmes : manipulent de nombreuses structures
exemple : getpwent()
‣ récupération formatée des entrées de /etc/passwd
‣ manipule une structure struct passwd
- déclaration dans le fichier en-tête pwd.h
- voir manuel getpwent()
ITC34 - Partie C / C++
79
‣ stocke plusieurs valeurs du même type
‣ type des valeurs à stocker annoncé dans la déclaration du tableau
‣ taille statique :
- taille = nombre maximal d’éléments pouvant être stockés
➡ la taille doit être connue avant utilisation
➡ réservation de la mémoire nécessaire
‣ nombre d’éléments réellement stockés < taille
‣ en général : variable supplémentaire pour nombre d'éléments stockés
Déclaration d’un tableau :
‣ type_element nom_tableau [ taille_tableau ] ;
int tabEntiers[10] ;
float tabFlottant[15] ;
Benoît Darties
ITC34 - Partie C / C++
Les tableaux
80
Benoît Darties
Les tableaux
Manipulation des éléments du tableau
Tableaux multi-dimensionnels
‣ Cellules du tableau numérotées par des indices
- indices numérotés de 0 à taille - 1
‣ désignation de l’élément d’indice i : nom_tableau[ i ]
‣ Déclaration successives des dimensions
// déclaration
int matriceEntiers[10][20] ;
float tabTriDimFlottant [45][50][60];
int tabEntiers[10]
tabEntiers[0]
tabEntiers[4]
tabEntiers[9]
int tabEntiers[10] ; // déclaration tableau de 10 entiers
int a;
tabEntiers[4] = 54; // cellule d’indice 4 affectée à 54
a = tabEntiers[4]; // lecture de la cellule d’indice 4
ITC34 - Partie C / C++
81
Benoît Darties
// manipulation
matriceEntiers[9][5] = 6;
tabTriDimFlottant[10][10][10] = matriceEntiers[9][5] * 4.0;
matriceEntiers[10][5] = 6; // ERREUR !
// 10 est un indice hors limite
// possible erreur de segmentation de la mémoire
// ou écrasement d’une valeur
// Que se passe-t’il en mémoire ?
ITC34 - Partie C / C++
82
Benoît Darties
Téléchargement