SlideShare une entreprise Scribd logo
1
Langage C
Khalid MOUSSAID
2
Utilisateur
Unités périphériques
Unité centrale
Mémoire
centrale
unité
d'entrée
unité
de sortie
Données
Résultats
L'utilisateur et l'ordinateur
3
Mémoire centrale
Données
Programme
4
Unité élémentaire = système physique bistable (Bit)
(2 états)
∀ l'information = {0, 1}
nombre, texte, image, son
représentation des informations
en Mémoire
5
décimal binaire
0 0
2 10
3 11
7 111
Nombre
Exemples de représentation
6
Un octet = 8 bits
ex : 1 0 1 1 0 1 1 0
Combien d'objets distincts peut-on représenter
avec un octet ?
Octet ?
7
1 bit
1 octet
1 Kilo octet (Ko) = 1024 octets
1 Mega octet (Mo) = 1024 Ko
= 1024 * 1024 octets
1 giga octet (Go) = 1024 Mo
Volume mémoire
8
1 octet
1 octet
1 octet
1 octet
1 octet
1 octet
Organisation de l’information en mémoire
Chaque octet de la mémoire est repéré par une adresse
Adresse
Le nombre d’octet
occupés par une
information dépend
du type de cette
information:
entier, réel,
Caractère, chaîne
de caractères
9
32 espaces
33 !
34 "
35 #
36 $
37 %
38 &
39 `
40 (
41 )
42 *
43 +
44 ,
45 -
46 .
47 /
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
58 :
59 ;
60 <
61 =
62 >
63 ?
64 @
65 A
66 B
67 C
68 D
69 E
70 F
71 G
72 H
73 I
74 J
75 K
76 L
77 M
78 N
79 O
80 P
81 Q
82 R
83 S
84 T
85 U
86 V
87 W
88 X
89 Y
90 Z
91 
92 
93 ]
94 ^
95 —
96 -
97 a
98 b
99 c
100 d
101 e
102 f
103 g
104 h
105 i
106 j
107 k
108 l
109 m
110 n
111 o
112 p
113 q
114 r
115 s
116 t
117 u
118 v
119 w
120 x
121 y
122 z
123 {
124 
125 }
126 ~
127
Représentation des caractères sur un octet
(ASCII)
10
Instructions
Algorithme Programme exécutables
par la machine
langage
de
programmation
compilateur
Algorithmes - Programmes
11
"Une suite finie de règles à appliquer dans
un ordre déterminé à un nombre fini de
données pour arriver, en un nombre fini
d'étapes, à un certain résultat, et cela
indépendamment des données".
Algorithme
12
langage machine le seul compréhensible
par la machine
langage assembleur très proche du langage
machine, mais plus
explicite
langage évolué proche de la description
(3ème génération) des algorithmes
C, FORTRAN, PASCAL
langage facilite la recherche
4è génération d'information dans les
bases de données (SQL)
Langages de programmation ?
Bas niveau
Haut niveau
13
Langage C
Conception
et description
d'un algorithme
Programme
C
programme
objet
exécutable
Langage C compilation
14
programme C
COMPILATEUR
programme objet
Editeur de liens
programme exécutable
données résultat
Exécution d'un programme
15
Historique
Pour développer une version portable du système d'exploitation UNIX, en
1972 dans les 'Bell Laboratories' Dennis M. Ritchie a conçu un langage
de programmation structuré, mais très 'près' de la machine: c’est la
naissance du langage C.
K&R-C
En 1978, le duo Brian W. Kernighan / Dennis M. Ritchie a publié la
définition classique du langage C (connue sous le nom de standard K&R-
C ) dans un livre intitulé 'The C Programming Language'.
ANSI-C
En 1983, le 'American National Standards Institute' (ANSI) chargeait une
commission de mettre au point 'une définition explicite et indépendante de
la machine pour le langage C', qui devrait quand même conserver l'esprit
du langage. Le résultat était le standard ANSI-C
16
Avantages
Le grand succès du langage C s'explique par les avantages suivants; C
est un langage:
(1) universel :
C n'est pas orienté vers un domaine d'applications spéciales, comme par
exemple FORTRAN (applications scientifiques et techniques) ou
COBOL (applications commerciales ou traitant de grandes quantités de
données).
(2) compact :
C est basé sur un noyau de fonctions et d'opérateurs limité, qui permet la
formulation d'expressions simples, mais efficaces.
(3) moderne :
C est un langage structuré, déclaratif et récursif; il offre des structures
de contrôle et de déclaration comparables à celles des autres grands
langages de ce temps (FORTRAN, ALGOL68, PASCAL).
17
4) près de la machine :
comme C a été développé en premier lieu pour programmer le système
d'exploitation UNIX, il offre des opérateurs qui sont très proches de
ceux du langage machine et des fonctions qui permettent un accès
simple et direct aux fonctions internes de l'ordinateur (p.ex: la gestion
de la mémoire).
(5) rapide :
comme C permet d'utiliser des expressions et des opérateurs qui sont
très proches du langage machine, il est possible de développer des
programmes efficients et rapides.
(6) indépendant de la machine :
bien que C soit un langage près de la machine, il peut être utilisé sur
n'importe quel système en possession d'un compilateur C. Au début C
était surtout le langage des systèmes travaillant sous UNIX, aujourd'hui
C est devenu le langage de programmation standard dans le domaine des
micro-ordinateurs.
18
(7) portable :
en respectant le standard ANSI-C, il est possible d'utiliser le même
programme sur tout autre système (autre hardware, autre système
d'exploitation), simplement en le recompilant.
(8) extensible :
C ne se compose pas seulement des fonctions standard; le langage est
animé par des bibliothèques de fonctions privées ou livrées par de
nombreuses maisons de développement.
19
Présentation du langage
 Premières notions
Les types de base
Les entiers, les réels (sous ensemble fini des rationnels), et les caractères.
Les entiers:
Définition Description Dom min Dom max Nbre
octets
short int Entier court -32768 +32767 2 octet
int Entier standard -32768 +32767 2 octet
long int Entier long -2147483648 +21474836487 4 octet
20
Définition Description Dom min Dom max Nbre
octets
unsigned short int Entier court 0 65535 2 octet
unsigned int Entier standard 0 65535 2 octet
unsigned long int Entier long 0 4294967295 4 octet
Il est possible de travailler avec un entier non signé
Les caractères
Définition Description Dom min Dom max Nbre
octets
unsigned char Caractère non signé 0 255 1 octet
char caractère 0 255 1octet
signed char Caractère signé -128 127 1 octet
21
Les nombres en virgule flottante
<+|-> <mantisse> * 10<exposant>
<+|-> est le signe positif ou négatif du nombre
<mantisse> est un décimal positif avec un seul chiffre devant la
virgule
<exposant> est un entier relatif
En C, nous avons le choix entre trois types de rationnels: float,
double et long double. Dans le tableau ci-dessous, vous trouverez
leurs caractéristiques:
Définition Description mantisse Dom min Dom max Nbre
octets
float simple 6 -3.4 * 10-38 3.4 * 1038 4 octet
double double 15 -1.7 * 10-308 1.7 * 10308 8 octet
long double Long double 19 -3.4 * 10-4932 1.1 * 104932 10 octet
22
2. Les variables
Emplacement mémoire dans lequel est codé une information que l’on
peut modifier et utiliser grâce à un identificateur.
Toute variable doit être déclarée avant d’être utilisée
Syntaxe: <type> < identificateur>
Identificateur: composé de chiffres, de lettres et du caractère _ ; son
premier caractère ne doit pas être un chiffre.
Les majuscules et les minscules ne sont pas équivalentes. Ainsi :
le_langage_C et le_lAngae_C sont deux identificateurs distincts.
Exemple: unsigned long int le nombre; int I_entier;
double le_reel; unsigned char le_caractère;
23
3. Les constantes
Contrairement à une variable, une constante ne peut être modifiée.
Les constantes entières
Elles peuvent être représentées selon trois systèmes de numération:
décimale, octale(précédée de 0) et héxadécimale (précédée de 0x ou 0X)
Base décimale Base octale Base
héxadécimale
Représentation
binaire
100 0144 0X64 1100100
255 0377 0xff 11111111
65536 0200000 0X10000 10000000000000000
24
Selon sa valeur, une constante entière est codé soit comme: un
entier, un entier long. On peut même forcer le codage en entier
long en ajoutant la lettre l ou L. les constantes non signées
s’écrivent avec un u ou U à la fin.
Exemples: 0XAL, 5u, 6l, 10uL, 041lU, 25UL, 0x78ul
Les constantes en virgule flottante
•En notation décimale: <partie entière>.<partie fractionnaire>
Exemples: 3.14159, 1000.001, 2001.007, .125
•En notation scientifique:
<partie entière>.<partie fractionnaire>e[signe]<nombre entier>
<partie entière>.<partie fractionnaire>E[signe]<nombre entier>
Exemples: 3.14159e0, 0.314159E+1, 314.159e-2
25
Les constantes caractères
Une constante caractère s’écrit en encadrant le caractère par deux
apostrophes. Exemple: 'A', '$', 'a', 'o', '0', '1', etc…
Il est possible de remplacer le caractère, par exemple A, par son code
ASCII (65) exprimé en octale précédé par  ou héxadécimale précédé
par x. Les constantes 'A' , '101' et 'x41' sont identiques.
Code décimal caractère séquence signification
7 BEL a Sonnette
8 BS b Retour arrière
9 HT t Tab horizontale
10 NL n Changement de ligne
11 VT v Tab verticale
12 FF f Saut de page
13 RC r Retour chariot
26
t o u l e
s m o n d e
Les constantes chaîne de caractères
Une constante chaîne de caractères est une suite finie de caractères,
délimitée par des guillemets.
Une chaîne se termine impérativement par le caractère non affichable
NULL (code ASCII: zéro) qui est ajouté automatiquement par le
compilateur.
Exemple: en mémoire la chaîne "tous le monde" est représentée par:
0
Attention ne confondons pas le caractère 'a' et la chaîne "a"
qui, elle comprend deux caractère 'a' et '0'.
27
Utilisation des constantes:
•Soitdirectement:
I_entier = 20; (on affecte 20 à la variable I_entier),
•Soit en définissant un nom symbolique à la constante par:
# define MAX 20
Et I_entier = MAX;
La directive #define s'adresse au préprocesseur; celui-ci remplace
toutes les occurrences MAX par 20 et ceci avant la compilation.
Exemples: #define MESSAGE ”le langage C ”
#define PI 3.14159
•Soit en utilisant un identificateur déclaré avec le mot-clé const
Syntaxe: const <type> <identificateur> = <valeur>;
Exemples: const double pi =3.14159; const int max = 20;
28
4. Les opérateurs
Les opérateurs, les variables et les constantes permettent de construire
des expressions. En C, une expression a toujours un type et une valeur.
Une instruction élémentaire est obtenue en ajoutant à une expression le
caractère ;
Les opérateurs arithmétiques
Ce sont les opérateurs + (addition), - (soustraction), * (multiplication),
/ (division) et % (reste de la division entière).
Syntaxe: <expression numérique> op <expression numérique>
Où op est l’un des opérateurs +, -, *.
< expression> / < expression> où l’une des deux expression est de
type flottant. Le résultat est de type flottant.
29
<expression entière> / <expression entière> . Le résultat est entier
<expression entière> % <expression entière> . Le résultat est entier
Exemples: 7 * 5 et 7.0 * 5 sont respectivement de type entier et de type
réel. Les expressions 7.0 / 5, 7 / 5 et 7 % 5 valent respectivement
1.4, 1 et 2. Notez bien qu’il y a deux divisions et un seul symbole.
L’affectation
Syntaxe: <variable> = < expression>
Le résultat de l’expression est convertit, si cela a un sens, au type de la
variable.
Déclarons trois variables: int I_entier, le_nombre;
double le_reel;
Les instructions I_entier = 3 ; et le_reel = 3.14 sont des instructions
d’affectation. L’affectation en cascade le_nombre = I_entier = 3 ; est
correcte.
30
L’incrémentation, la décrémentation
Syntaxe: <variable> op ou op <variable> où op est l’un des opérateurs
++ ou –
L’expression le_nombre = le nombre + 1 peut être remplacée par
le_nombre++ ou ++le_nombre.
Attention la valeur de l’expression le_nombre++ est égale à la valeur de
nombre avant l’incrémentation alors que ++le_nombre a pour valeur
le_nombre après l’incrémentation.
Ainsi la séquence d’instructions
Le_nombre = 3; I_entier = le_nombre++; le_reel = ++le_nombre
A pour résultat d’affecter 3 à I_entier et 5 à le_reel, le_nomre contenant
en définitive 5.
L’opérateur de décrémentation a le même comportement que le précédent.
Ainsi l’instruction le_reel--; diminue de 1 le contenu de le_reel.
31
Les affectations généralisées: +=, -=, *=, /=, %=, etc
L’expression I_entier = I_entier + 2 est équivalente à I_entier += 2
L’instruction I_entier = I_entier + le_nombre; est équivalente à
I_entier += le_nombre;
La syntaxe générale est: <variable> op <expression> où op est l’un des
opérateurs +=, -=, *=, /=, %=
Exemple : le_nombre contenant 5. Après la séquence :
I_entier = 8; I_entier += le_nombre; I_entier contient 13.
Les opérateurs relationnels:
égal à (==), différent !=, strictement supérieur à (>), strictement inférieur à
(<), supérieur à (>=) et inférieur à (<=).
32
La syntaxe est : <variable> op <expression> où op est l’un des opérateurs
==, !=,<, >, <=, >=.
Exemples: si I_entier contient 3 , le_nombre 2 et le_reel 3.
Les expressions I_entier==le_nombre, I_entier >4, le_reel<=le_nombre
sont fausses et valent donc 0. De même les expressions I_entier != 5,
le_reel == I_entier, le_nombre < 14 sont vraies et valent 1.
Les opérateurs logiques:
Ce sont les connecteurs ET et OU ainsi que la négation; ils sont représentés
respectivement pa && , ||, et !.
La syntaxe: <expression numérique> op <expression numérique>
où op est l’un des opérateurs && , ||.
!= <expression numérique>
33
Les opérateurs de traitement de bits:
complémentation ~ dans la représentation binaire, tous les bits à 1
sont mis à 0 et réciproquement.
Syntaxe: ~ <expression entière>
Exemple: la représentation de 10 est : 0000000000001010
la représentation de ~10 est : 1111111111110101
les opérateurs de traitement de bits:
syntaxe : <expression entière> OP <expression entière>
OP est l ’un des opérateurs &, | ou ^
& 0 1
0 0 0
1 0 1
| 0 1
0 0 1
1 1 1
^ 0 1
0 0 1
1 1 0
34
Exemple:
la représentation de binaire de 65 est : 0000000001000001
la représentation de binaire de 9 est : 0000000000001001
la représentation de binaire de 65 & 9 est : 0000000000000001
la représentation de binaire de 65 | 9 est : 0000000001001001
la représentation de binaire de 65 ^ 9 est : 0000000001001000
les opérateurs de décalage:
ils permettent de décaler vers la droite (>>) ou vers la gauche (<<)
tous les bits d ’un nombre entier.
Syntaxe: <expression entière> OP <expression entière>
OP est l ’un des opérateurs << ou >>
Exemple:
la représentation de binaire de 65 <<9 est : 1000001000000000
la représentation de binaire de 65 >>3 est : 0000000000001000
35
Les opérateurs & et sizeof().
L ’opérateur & permet de connaître l ’adresse ( l ’emplacement
mémoire) d ’une variable.
Exemple : & I_entier désigne l ’endroit où est la variable I_entier.
Pour connaître la taille on utilise l ’opérateur sizeof().
Syntaxe : & <variable>
sizeof ( <variable>)
sizeof (<type>)
& I_entier I_entier
36
L ’opérateur conditionnel
syntaxe : <expressionC> ? <expression1> : <expression2>
la valeur du résultat est la valeur de l ’expression1 si l ’expressionC est
différente de zéro et expression2 sinon.
Exemple : l ’expression (I_entier == 8 ? I_entier / 2 : 7) a pour
valeur 4 si I_entier vaut 8 et 7 dans le cas contraire.
L ’opérateur de coercition
syntaxe : (<type>) <expression>
il force la conversion du type de la valeur d ’une expression.
Exemple : 012 est de type entier et (double)012 est de type double
si le_reel est de type float, (unsigned long int)le_reel est de type
unsugned long int; la valeur étant correctement arrondie.
37
La virgule est un opérateur
il permet de construire une expression composée.
Syntaxe : <expression1> , <expression2>
l ’expression1 puis l ’expression2 sont évaluées. Le résultat a pour
type et a pour valeur ceux de l ’expression 2.
Exemple : après l ’instruction :
le_nombre = (I_entier = 4 , I_entier ++, I_entier * 3);
le_nombre vaut 15.
L ’opérateur unaire - est l ’opposé
par symétrie, l ’opérateur + est défini.
Exemple : +5, -5, +I_entier, -I_entier.
38
Opérateur Niveau Symbole Associativité
De structure
Unaire
Multiplicatif
Additif
De décalage
D’inégalité
D’égalité
De bit à bit
De bit à bit
De bit à bit
Conjonction
Disjonction
Conditionnel
Exp composée
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
( ) . -> [ ]
~ ! ++ -- - + (<type>)
(indirection), & sizeof
* / %
+ -
>> <<
< <= > >=
== !=
&
^
|
&&
||
? :
= += -= *= /= %=
&= ^= |= <<= >>=
,
De gauche vers droite
De droite vers gauche
De gauche vers droite
De gauche vers droite
De gauche vers droite
De gauche vers droite
De gauche vers droite
De gauche vers droite
De gauche vers droite
De gauche vers droite
De gauche vers droite
De gauche vers droite
De droite vers gauche
De droite vers gauche
De gauche vers droite
Tableau récapitulatif des opérateurs
39
Les fonctions
Définition :
les fonctions sont les sous-programmes du C; elles permettent de
regrouper des instructions et de lancer leur exécution grâce à un
identificateur.
Syntaxe :
[type] <identificateur>(liste des paramètres formels])
{
. . .
< corps de la fonction>
. . .
} /* fin de la fonction
40
Remarques :
le type d ’une fonction est déterminé par le type du résultat qu ’elle
retourne.
Une fonction qui ne renvoie pas de valeur au programme appelant est
de type void.
Le type par défaut d ’une fonction est int.
Dès qu’une instruction de retour est rencontrée, l ’exécution de la
fonction s ’interrompt.
Syntaxe : return;
return <expression>;
return (<expression>);
si la fonction ne contient pas d ’instruction « return », elle s ’achève
automatiquement à la fin de son bloc.
41
Exemple :
définition :
int ce_double (int tel_nb)
{
int res;
res = tel_nb * 2;
return res;
} /* fin ce_double */
Appel :
ce_double(41.125); ou ce_double(le_nb);
remarque: l ’argument 41.125 est converti en entier à l ’appel.
42
Déclaration de fonction
la déclaration d ’une fonction a pour but d ’avertir le compilateur que
cet objet va être utilisé et de lui préciser le type de son résultat et de
chacun de ses paramètres formels éventuels.
Syntaxe : <type> <identificateur de fonction> (liste des paramètres);
Exemple : déclaration du prototype de la fonction précédente:
int ce_double (int tel_nb); ou int ce_double (int);
Remarque : les prototypes des fonctions des bibliothèques sont
déclarés dans des fichiers « en-tête »; il est souhaitable d ’inclure le
fichier correspondant lorsque l ’une de ces fonctions est utilisée grâce
à la directive de compilation include :
# include <stdio.h>
43
 Deux fonctions d ’E/S : printf et scanf
le prototype de ces fonctions est dans le fichier en-tête stdio.h.
la fonction printf
pour afficher des résultats on utilise la fonction printf.
Syntaxe : printf(<format>, [expression1] [, expression2]. . .)
le format est une chaîne de caractères comprenant éventuellement les
spécifications de type des expression1, expression2 etc.. à afficher.
Exemple : le résultat de l ’instruction printf (" coucou le monde!n");
est coucou le monde!
De même printf("le double de %d est %d.n", 8, 16);
donne le double de 8 es 16 .
Printf("Nous étudions n %s sous n UNIX. n", "le langage C")
donne:
44
Nous étudions
le langage C sous
Unix.
Il est possible de fixer la largeur du champ d'affichage pour
l'argument.
Exemple : printf("valeurs : %5d%10.3fn", 14, 3.1459);
donne : 14 3.142
la fonction scanf
permet de saisir des données au clavier et de les ranger dans une
variable.
Syntaxe : scanf (<format>, <adresse d'une variable>)
le format est une chaîne réduite à la spécification de données à saisir.
Exemple : saisir une données entière et la ranger dans la variable
"int" I_entier,
scanf("%d", &I_entier);
45
Le type de l’expression Spécificateur d’affichage Spécificateur de saisie
Int (écriture décimale)
Int (écriture décimale ou
octale ou hexadécimale)
int (écriture octale)
int (écriture hexadécimale)
int unsigned
short int
long int
char
float (écriture décimale)
double (écriture décimale)
long double (décimale)
float (écriture scientifique)
double (scientifique)
long double (scientifique)
chaîne de caractères
%d ou %i
%o
%x
%u
%hd ou %ho ou %hx ou
%hu
%ld ou %lo ou %lx ou
%lu
%c
%f
%f
%Lf
%e ou % E
%e ou %E
%Le ou %LE
%s
%d
%i
%o
%x
%u (décimale)
%hd ou %ho ou %hx ou
%hu
%ld ou %lo ou %lx ou
%lu
%c
%f
%lf
%Lf
%e
%le
%Le
%s
Les spécificateurs de format
46
Structure d'un programme
Organisation d'un programme C
un programme C se présente sous la forme d'un ou plusieurs fichiers
sources.
Chaque fichier contient des déclarations et des définitions de
variables et de fonctions.
La définition d'une fonction contient les déclarations de son type et
de la liste (éventuellement vide) de ses paramètres et un bloc. Le
programme doit contenir une et une seule fonction de nom main :
c'est le point d'entrée du programme.
Un bloc commence par le symbole { , contient des déclarations de
variables et une suite d'instructions et se termine par le symbole }.
Un bloc est appelé aussi "instruction composée".
47
Une instruction est soit une instruction élémentaire (elle doit se
terminer par un point virgule), soit un bloc, soit une instruction de
contrôle. Notez que si un bloc peut contenir un autre bloc, une fonction
ne peut contenir la définition d'une autre fonction.
Des directives de compilation apparaissent aussi dans les fichiers
sources.
Exemples :
Le premier programme:
void main (void)
{
printf (" bonjour, tous le monde!n");
} /* main */
ce programme est écrit à l'aide d'un éditeur de texte et sauvegardé sous
le nom premier.c. Pour le compiler sous Unix (et aussi Linux) il faut
exécuter la commande cc premier.c. Le résultat de la compilation et
de l'édition de liens est alors le fichier exécutable a.out
48
Deuxième programme : taille en octets des types de base
void main(void)
{
printf(" la taille d'un entier est : %d octets n",sizeof(int));
printf(" la taille d'un entier court est : %d octets n",sizeof(short int));
printf(" la taille d'un entier long est : %d octets n",sizeof(long int));
printf(" la taille d'un caractère est : %d octet n",sizeof(char));
printf(" la taille d'un "float" est : %d octets n",sizeof(float));
printf(" la taille d'un "double" est : %d octets n",sizeof(double));
printf("et celle d'un "long double" est:%d octetsn",sizeof(long double));
} /* main de taille.c */
compilons:
cour_C> cc taille.c
49
Exécutons:
cours_C> a.out
la taille d'un entier est : 4 octets
la taille d'un entier court est : 2 octets
la taille d'un entier long est : 4 octets
la taille d'un caractère est : 1 octet
la taille d'un "float" est : 4 octets
la taille d'un "double" est : 8 octets
et celle d'un "long double est : 12 octets
50
Troisième exemple: utilisation de scanf
void main (void)
{
float le_flottant; double le_reel; long double le_reel_double;
printf("entrez un nombre a virgule:");
scanf("%f",&le_flottant);
printf("vous avez tapé %f.n", le_flottant);
printf("Affichage du même nombre avec format : %8.3f.n,le_flottant);
printf("Entrez un nombre a virgule:");
scanf("%lf",&le_reel);
printf("vous avez tapé %f.n", le_reel);
printf("Affichage du même nombre avec format : %16.3f.n,le_reel);
printf("Entrez un nombre a virgule:");
scanf("%Lf",&le_reel_double);
printf("vous avez tapé %Lf.n", le_reel_double);
printf("Affichage du nombre avec format :%20.3Lf.n,le_reel_double);
} /* main de scanf.c */
51
Cours_C> cc scanf.c
cours_C> a.out
Entrez un nombre a virgule : 123456.789012345123456789
Vous avez tapé 123456.789062.
Affichage du même nombre avec format : 123456.789.
Entrez un nombre a virgule : 1234567890123.45123456789
Vous avez tapé 1234567890123.451234.
Affichage du même nombre avec format : 1234567890123.451.
Entrez un nombre a virgule : 123456789012345.123456789
Vous avez tapé 123456789012345.123456.
Affichage du même nombre avec format : 123456789012345.123.
52
Compilation
Sous Unix (Linux) la commande cc lance plusieurs programmes:
•le préprocesseur
•le compilateur
•l'assembleur
•l'éditeur de liens (qui résout les références externes: ex printf et scanf)
Plusieurs syntaxes sont possibles:
cc fichier.c l'exécutable a pour nom a.out.
cc fichier.c -o fichier l'exécutable a pour nom fichier.
cc -c fichier.c compilation sans édition de liens. Le résultat
d'assemlage est mis dans le fichier fichier.o.
cc fichier1.c fichier2.c fichier3.c -o resultat
si le programme est réparti dans plusieurs fichiers sources.
53
Les structures de contrôle
54
Les conditionnelles :
if…else (1)
if (condition)
{
instructions;
}
condition
instructions
vrai
faux
55
Les conditionnelles :
if…else (2)
if (condition)
{
instructions1;
}
else
{
instructions2;
}
condition
instructions1
vrai faux
instructions2
56
Les conditionnelles :
if…else (3)
int a,b,c,d;
if (a<b)
{
if (c<d)
{
instructions1;
}
else
{
instructions2;
}
}
…
…
else
{
instructions3;
}
57
Les conditionnelles :
switch…case (1)
switch (expression)
{
case constante1:
instructions1;
break;
case constante2:
instructions2;
break;
…
…
default:
instructionsDefaul
t;
break;
}
58
Les conditionnelles :
switch…case (2)
expression
constante1 default
instructionsD
instructions1 instructions2 ...
59
Les itérations :
La boucle for
• Syntaxe :
for (exp1;exp2;exp3)
{
instructions;
}
• Toutes ces expressions influent sur la variable
d’itérations qui compte le nombre d’itérations
• exp1 : Initialisation
• exp2 : Condition d’arrêt
• exp3 : Mise à jour
60
Les itérations :
La boucle for
exp2
exp1
vrai
faux
instructions
exp3
Initialisation
Condition d’arrêt
Mise à jour
61
Les itérations :
La boucle while
• Syntaxe :
while (condition)
{
instructions;
}
Tant que condition
vraie exécuter les
instructions
condition
instructions
vrai
faux
62
Les itérations :
La boucle do…while
• Syntaxe :
do
{
instructions;
}
while (condition);
Exécuter les
instructions tant que
condition vraie
condition
instructions
vrai
faux
63
Les itérations
• Utilisation des différents types de boucles :
– for : boucle basée sur une variable d’itération dont on
connaît a priori le début et la fin
– while ou do…while : boucle dont on ignore a priori
quand arrivera la condition de fin
• Une boucle doit respecter uniquement ses
conditions d’arrêt : pas de break !
64
Les fonctions
Définition :
les fonctions sont les sous-programmes du C; elles permettent de
regrouper des instructions et de lancer leur exécution grâce à un
identificateur.
Syntaxe :
[classe] [type] <identificateur>(liste des paramètres formels])
{
. . .
< corps de la fonction>
. . .
} /* fin de la fonction
65
Remarques :
•le type d ’une fonction est déterminé par le type du résultat qu ’elle
retourne.
•Une fonction qui ne renvoie pas de valeur au programme appelant est
de type void.
•Le type par défaut d ’une fonction est int.
•Par défaut la classe d’une fonction est "extern" c-a-d accessible par
toutes les fonctions du programme que celles-ci appartiennent ou non
au fichier où elle est définie. Par contre, une fonction de classe
"static" est locale à son fichier de définition; seules les fonctions du
même fichier peuvent l'appeler.
Exemple:
Considérons les deux fichiers prog_princ.c et fonction1.c
66
cours_C> cat prog_prin.c
void main(void)
{
affiche_le_message();
}/* prog_prin.c*/
cours_C> cat fonction1.c
Void affiche_le_message(void)
{
printf("bonjour tout le monde.n");
}/* fonction1.c*/
cours_C> cc prog_prin.c fonction1.c -o bonjour
prog_prin.c:
fonction1.c:
cours_C>bonjour
Bonjour tout le monde.
67
cours_C> cat fonction2.c
static void affiche_le_message(void)
{
printf("bonjour tout le monde.n");
}/* fonction1.c*/
cours_C> cc prog_prin.c fonction2.c -o bonjour
prog_prin.c:
fonction1.c:
Id: Undefined –
.affiche_le_message
_affiche_le_message
_end
cours_C>
La fonction affiche_le_message est locale au fichier fonction2.c
68
•Dès qu’une instruction de retour est rencontrée, l ’exécution de la
fonction s ’interrompt.
Syntaxe : return;
return <expression>;
return (<expression>);
si la fonction ne contient pas d ’instruction « return », elle s ’achève
automatiquement à la fin de son bloc.
•La compilation s'effectue fichier par fichier, le compilateur peut
rencontrer une référence à une fonction définie dans un autre fichier:
il ignore alors son type; il lui attribue systématiquement le type int.
Exemple:
Le programme principal main affiche le résultat retourné (3.14159)
Par une fonction ce_reel. Ces deux objets sont définis dans des
fichiers différents.
69
cours_C> cat p_princ1.c
void main(void)
{
double le_reel;
le_reel = ce_reel();
Printf(" valeur de le_reel : %f .n", le_reel);
}/* main de p_prin1.c*/
cours_C> cat fonction3.c
double ce_reel(void)
{
return 3.14159;
} /* fonct3.c*/
cour_C>cc p_prin1.c fonct3.c -o echange
p_prin1.c :
fonct.c:
cour_C>echange
Valeur de le_reel : 1074340345.000000
Pour éviter ce genre d'erreur, il faut appliquer la règle suivante:
Tout objet utilisé doit être au préalable déclaré.
70
La déclaration d'une fonction a por but d'avertir le compilateur que cet
objet va être utilisé et de lui préciser le type de son résultat et de chacun
de ses paramètres formels éventuels.
Une fonction est déclarée dans un fichier à partir :
* soit de sa définition (en-tête + corps),
* soit de la simple donnée de son prototype:
<type> <identificateur de fonction> (liste des paramètres) ;
Exemple: modifions le programme p_prin.c précédent.
cours_C> cat prog_prin2.c
double ce_reel(void) /* prototype de la fonction ce_reel() */
void main(void)
{
double le_reel;
le_reel = ce_reel();
printf(" valeur de le_reel : %f .n", le_reel);
}/* main de p_prin1.c*/
71
Exemple de déclaration et d'appel de fonction
Cours_C> cat bissextile.c
#include <stdio.h>
int I_annee;
int cette_annee_est bissextile(void)
{
if (!(I_annee % 4) && I_annee % 100 || !(I_annee % 400))
return 1;
else return 0;
} /* cette année est bissextile */
void main(void)
{
printf(" Donnez une année :");
scanf("%d", &I_annee);
if (cette_annee_est_bissextile())
printf("l'année %d est bissextile.n", I_annee);
else
printf("l'année %d n'est pas bissextile.n", I_annee);
}
72
cours_C> cat pgcd1.c
#include <stdio.h>
long int le_a , le_b;
long int ce_pgcd(void)
{
while ( le_a != le_b)
if (le_a > le_b)
le_a - = le_b;
else le_b - = le_a;
return le_a;
} /* ce_pgcd */
void main(void)
{
printf("Donnez deux nombres >0");
scanf("%ld %ld", &le_a, &le_b);
printf(" le pgcd est %ld. n", ce_pgcd());
} /* main de pgcd1.c */
73
Les paramètres formels
Une écriture plus élégante de la fonction ce_pgcd, consiste à utiliser les
paramètres formels.
cours_C> cat pgcd2.c
#include <stdio.h>
long int ce_pgcd(long int tel_a , tel_b;)
{ while ( tel_a != tel_b)
if (tel_a > tel_b) tel_a - = tel_b;
else tel_b - = tel_a;
return tel_a;
} /* ce_pgcd */
void main(void)
{ long int le_a , le_b;
printf("Donnez deux nombres >0");
scanf("%ld %ld", &le_a, &le_b);
printf("le pgcd de %ld et %ld est %ld.n",le_a,le_b, ce_pgcd(le_a,le_b));
} /* main de pgcd1.c */
74
Le mécanisme d'appel est le suivant:
• dans le programme appelant les arguments éventuels sont évalués,
•Pour chaque paramètre, une variable "interne" à la fonction appelée est
crée et reçoit la valeur de l'argument; cette variable est détruite dès que la
fonction appelée se termine.
180
135
le_a
le_b
main
180
tel_a
tel_b
135
Ce_pgcd
Ce_pgcd()
travaille sur
des copies
et non sur
les
originaux
Les variables le_a et le_b sont locales à la fonction main et ne sont donc
pas accessibles de la fonction ce_pgcd.
75
La récursivité
Une fonction est dite récursive si elle s'appelle elle-même.
Par exemple, réécrivons la fonction ce_pgcd en appliquant
strictement la définition :
long int ce_pgcd( long int tel_a , long int tel_b)
{
if (tel_a == tel_b )
return tel_a ;
else
if ( tel_a > tel_b )
return ce_pgcd( tel_a -tel_b , tel_b )
else
return ce_pgcd( tel_a , tel_b -tel_a )
} /* ce pgcd */
Une fonction récursive doit contenir une condition d'arrêt.
76
Les variables
Déclaration et définition d'une variable.
La déclaration précise les caractéristiques d'une variable; la
définition lui réserve aussi de la place en mémoire: elle est
alors créée. Cette réservation s'appelle l'allocation; elle peut
intervenir soit à la compilation, soit à l'exécution.
Toute variable doit être déclarée avant toute utilisation.
Distinguons trois sortes de variable.
a) Les variables de fichier: elles sont déclarées à l'extérieur
de toute fonction.
b) Les variables de bloc : elles sont déclarées à l'intérieur
d'un bloc.
c) Les paramètres d'une fonction
77
Initialisation.
En C, initialiser une variable c'est lui affecter une valeur au
moment de son allocation; l'affectation apparaît donc dans
la définition. Syntaxe :
[classe] <type> <identificateur> = <expression>
Exemple
int I_entier = 12 ;
A chaque fois que la variable l_entier est créée, le nombre
12 lui est affecté
78
Visibilité d'une variable.
Rappelons qu'une variable doit être déclarée avant son
utilisation et que la portée d'une déclaration est le fichier.
a) Une variable de fichier est visible (utilisable) de sa
déclaration jusqu'à la fin du fichier.
b) Un paramètre de fonction n'est visible que du bloc de
fonction.
c) Une variable de bloc n'est visible que de son bloc.
Toutefois la déclaration d'un paramètre ou d'une variable
de bloc annule localement la déclaration de toute variable
de même nom faite à l'extérieur de ce bloc. Ainsi :
79
Les variables de fichier I_entier et
le_reel ne sont visibles que des blocs
D et C.
Le paramètre I_entier de la fonction f
n'est visible que des blocs A et B.
La variable le_reel du bloc B n'est
visible que de B.
le_reel représente trois variables
distinctes suivant que l'on se trouve
dans A, dans B ou dans C ou D.
80
Redéclaration d'une variable. Droit d'accès.
On peut redéclarer une variable de fichier, évidemment sous
le même nom et avec le même type, en faisant précéder cette
déclaration du mot clé extern. Exemple:
extern int I_entier ; . La redéclaration n'a de sens que si la
variable "originale" est accessible et est effectivement
déclarée et allouée (c'est à dire définie) "ailleurs" afin que
l'on puisse accéder à la donnée qu'elle contient.
Durée de vie d'une variable.
Une variable est :
-soit créée (allouée) à la compilation : elle existe en mémoire
tant que dure la tâche,
-soit créée à l'exécution à chaque fois que cela est nécessaire
et détruite à la fin de son utilisation.
81
Classe de mémorisation d'une variable.
En C, il y a quatre classes de variables: externe,
statique, automatique, registre.
Syntaxe complète de la déclaration d'une variable.
[classe] <type> <identificateur> [=<valeur>];
a)Externe.
Une variable de classe "extern " est :
-soit définie dans le fichier à l'extérieur de toute fonction
(c'est donc une variable de fichier). Elle est accessible à
partir de n'importe quel fichier du programme: elle est
"exportable"; bien sûr, elle doit être déclarée dans les
fichiers où elle n'est pas définie. On peut ne pas faire
précéder sa définition du terme "extern". Cette variable
est de classe extern au sens" global " .
82
-soit définie "ailleurs" .Il faut alors indiquer
explicitement sa classe par le mot clé extern. C'est
alors une simple déclaration; ce mécanisme permet
d'"importer" une variable globale d'un fichier à un
autre.
La norne fournit un moyen très simple de distinguer
ces "deux" points :
-une variable de fichier de classe extern est définie si
elle est initialisée et si le mot extern n'est pas
précisé,
-une variable de classe extern est simplement
déclarée si on spécifie le mot extem sans préciser
d'initialisation.
83
b) Statique.
Une variable de classe "static" est allouée à la compilation dans la
zone des données statiques; elle existe donc en mémoire tant que
Dure la tâche. Elle n'est accessible Que du bloc ou fichier où elle
est définie.
c) Automatique.
Une variable de classe "auto" est allouée à l'exécution dans la pile.
Elle est créée lorsque le bloc dans lequel elle est définie devient
actif; elle est détruite à la sortie du bloc.
d) Registre.
Une variable de classe "register" est allouée à l'exécution dans l'un
des registres de la machine. Elle est créée lorsque le bloc dans
lequel elle est déclarée devient actif; elle est détruite à la fin du
bloc. On ne peut pas connaître l'adresse d'une variable "register".
Si tous les registres sont occupés ou si sa taille ne lui permet pas
d'être mémorisée dans l'un d'eux, une variable "register" est
allouée automatiquement dans la pile.
84
Mettons en évidence la différence entre variable locale
statique et automatique.
void affiche( void ){
int le_nombre = 0; le_nombre ++ ;
(void)printf("% d ", le_nombre ) ;
} /* affiche () * /
int main( void ){
int I_indice = 0 ;
while ( ++I_indice < 10 ) affiche() ;
(void)printf("n") ; return 0;
} /* main de auto.c */
cours_C>cc auto.c
cours_C>a.out
1 1 1 1 1 1 1 1 1
Dans la fonction affiche la variable le_nombre est de classe auto
donc elle est créée et initialisée à chaque appel.
85
#include <stdio.h>
void affiche( void ){
static int le_nombre = 0;
++ le_nombre ;
(void)printf("% d ", le_nombre ) ; } /* affiche () * /
int main( void){
int I_indice = 0 ;
while ( ++I_indice < 10 ) affiche() ;
(void)printf("n") ; return 0;
} /* main de static.c * /
cours_C>cc static.c
cours_C>a.out
1 2 3 4 5 6 7 8 9
Ici la variable le_nombre est de classe "static" aussi elle a été
créée et initialisée à la compilation, et existe tant que dure la
tâche; elle conserve donc sa valeur entre chaque appel.
86
Les tableaux (1)
• « Structure de données permettant de
rassembler une suite de valeurs de même
type en leur donnant un nom commun et en
accédant aux valeurs de la suite par un
indice »
87
Les tableaux (2)
0 2 3 4 5 6
1
int anArray [7] -> 9 3 12 1 1 2
0
anArray[3]
v
void main()
{
int anArray[7];
anArray[0]=9;
anArray[1]=0;
anArray[2]=3;
...
}
!
88
Les tableaux (3)
0 2 3 4 5 6
1
float anArray[7] ->
anArray[3]
v
void main()
{
float anArray[7]={9.5,0.2,3.1,5.8,1,1.2,6};
anArray[0]=9.5;
anArray[1]=0.2;
anArray[2]=3.1;
...
}
9.5 0.2 3.1 5.8 1 1.2 6
89
Les tableaux (4)
• Parcours de la totalité d’un tableau :
#define ARRAY_SIZE 1000
for (i=0;i<ARRAY_SIZE;i++)
{
…
}
90
Les tableaux (5)
• Recherche dans un tableau :
#define ARRAY_SIZE 1000
void main()
{
int searchingArray[ARRAY_SIZE];
int element,i=0;
initialization(searchingArray,&element,ARRAY_SIZE);
while((i< ARRAY_SIZE) && (searchingArray[i]!=element))
i++;
if (i== ARRAY_SIZE)
printf("Element %d not found !n",element);
else
printf("Element %d found at indice %dn" ,element,i);
}
91
Les tableaux (6)
• Tableaux et fonctions
• Passage de paramètres
– void readMarks(float markArray[], int nbMark)
• Utilisation dans la fonction:
– markArray[3]=9.75
• Appel :
– readMarks(SMIMarks,nbStudentSMI);
92
Les tableaux (7)
• Résumé :
– Parcours de tous les éléments du tableau ->
boucle for
– Parcours partiel d’un tableau en connaissant les
bornes inférieures et supérieures -> boucle for
– Parcours partiel d’un tableau lorsque la borne
supérieure ou inférieure n’est pas connue ->
boucle while ou do…while
93
Les chaînes de caractères
• Chaîne de caractères -> tableau spécial
o
l
l
e
h 0
o
l
l
e
h
Chaîne de caractères
Tableau de caractères
Fin de chaîne
• Attention prévoir un caractère de plus pour le 0 !!!
94
Les chaînes de caractères (2)
• Ordinateur ne comprend que le binaire
• Représentation des caractères par un nombre entier :
c ’est l ’ASCII
• ASCII : American Standard Code for Information
Interchange
• Tableau de correspondance entre lettre et
représentation ASCII -> table ASCII
95
Les chaînes de caractères (3)
l’ASCII
• Proposé par l ’ANSI (AN Standards Institute) en 1963,
finalisé en 68, utilisé à partir de 80
• Créé par Bob Bemer d’IBM
• Codage sur 7 bits avec en plus l’escape caracter
• 32 premiers caractères sont des caractères de contrôle
(7 est une sonnerie, 8 effacement du caractère
précédent, 13 retour à la ligne, …)
96
Les chaînes de caractères (3)
l’ASCII
• Exemple de codage ASCII :
Notation ASCII décimale
Notation humaine
104 101 108 108 111 0
h e l l o 0
68 65 6C 6C 6F 0 Notation ASCII hexadécimale
97
Les chaînes de caractères (4)
l’ASCII
• C ’est l ’ordinateur qui gère la conversion
• Utiliser de préférence la notation humaine (c ’est plus
clair pour les humains…)
• ‘A’ est équivalent à 65, ‘a’ à 97, etc.
• Ex :
– char mLetter=‘a’+12;
98
Les chaînes de caractères (2)
0 2 3 4 5
1
char aString [6] ->
aString[3]
v
#include <string.h>
void main()
{
char aString[6]="hello0";
aString[0]=‘h’;
aString[1]=‘e’;
...
strcpy(aString,"hello");
}
0
o
l
l
e
h
99
Les chaînes de caractères (3)
• Initialisation d’une chaîne :
– Lors de la déclaration
– Element par élément
• Fonctions dédiées :
– scanf (stdio.h)
– strcpy (string.h)
100
Les chaînes de caractères (4)
• Affichage avec printf :
• printf(“%sn”,myString);
101
Les chaînes de caractères (5)
Les fonctions standard
• Longueur : length=strlen(myString);
• Copie : strcpy(myString,”hello”);
• Concaténation :strcat(myString,”lo”);
• Comparaison :strcmp(string1,string2);
• Transformation en entier :
integer=atoi(myString);
• Transformation en flottant :
floatingPoint=atof(myString);
102
Les tableaux à plusieurs
dimensions
• 2 dimensions
– Déclaration : int matrix[LINE_SIZE][COL_SIZE];
– Utilisation : matrix[4][3]=4;
• 3 dimensions
– Est-ce bien utile ?
103
Structures en C
• Tableau : ensemble de valeurs de même
type
• Structure : ensemble de valeurs de types
différents
• Une structure s’utilise comme un type de
données
104
Structures : Définition
struct Student
{
char firstName[50];
char lastName[50];
int age;
};
int main()
{
struct Student toto;
toto.age=19;
return 0;
}
Champ
Définition de la structure
Ne pas oublier le ;
Déclaration d’une variable
Accès aux champs avec .
105
Structures : Définition
• Définition globale ou dans le header (.h)
• mot-clef struct devant la déclaration de
variable (possibilité d’utiliser un typedef)
• . est l ’opérateur d ’accès aux champs
106
Structures : Imbrication
struct Date
{
int jour,mois,annee;
};
struct Etudiant
{
char nom[50];
char prenom[50];
int age;
struct Date dateInscription;
};
int main()
{
struct Etudiant toto;
toto.dateInscription.jour=1;
return 0;
}
107
Tableaux de structures
struct Etudiant
{
char nom[50];
char prenom[50];
int age;
};
int main()
{
struct Etudiant smi[50];
smi[0].age=19;
return 0;
}
108
Les pointeurs en C
109
Plan du cours
• La notion d'adresse mémoire
• La notion de pointeur
• Pointeurs et passage de paramètres
• Pointeurs et tableaux
• Pointeurs et chaînes de caractères
• Allocation dynamique de mémoire
• Les allocations mémoire en C
110
La notion d'adresse mémoire
La définition de variable int i = 5; peut être interprétée de 2 façons.
Point de vue conceptuel Point de vue du compilateur C
• i est un nom symbolique
qui désigne une variable
qui prend des valeurs entières
i 5
• i est une zone mémoire dimensionnée
pour contenir des valeurs entières
• le compilateur attribue une adresse
à i en mémoire
5
102
adresse mémoire
111
Accès à l'adresse mémoire d'une variable
• l'adresse d'une variable est une donnée en elle-même
=> on peut manipuler les adresses mémoire
• le langage C autorise :
-> l'accès à l'adresse mémoire d'une variable
-> la manipulation des adresses mémoire à l'aide d'opérateurs
-> la déclaration de variables dont les valeurs sont
des adresses mémoire (notion de pointeur)
• l'opérateur "&"
si i est une variable entière, alors &i est une expression dénotant
l'adresse de i
5
&i
112
La notion de pointeur
• Déclaration d'une variable pointeur sur un type
• Affectation à un pointeur
• L'opérateur *
pi *pi
variable pointeur variable pointée
l'opérateur * permet d'accéder
à la variable pointée : il sert
à déréférencer le pointeur
5
int i = 5; ==> pi = &i;
int * pi; /* pi est un pointeur sur entier */
char * pc; /* pc est un pointeur sur caractère */
-> on peut déclarer un pointeur sur un type quelconque
i ⇔* (&i)
113
Les opérations sur les pointeurs
•le déférencement "*"
• l'affectation "="
• les opérateurs de comparaison "==", "!="
• les opérateurs "+" et "-" sur les adresses
• la constante NULL est une valeur spéciale du fichier stdio.h
-> un pointeur à NULL ne pointe sur rien
• les opérations d'allocation dynamique de la mémoire malloc et de
désallocation free offertes par la librairie standard (fichier stdlib.h)
114
Un programme illustrant les pointeurs
main ()
{
int i = 5, j = 9;
int *p1, *p2; /* deux pointeurs sur entier */
p1 = &i; /* *p1 est la variable i */
p2 = p1; /* p2 désigne la variable pointée par p1, c'est à dire i */
*p1 = 9; /* la variable i est modifiée */
if (p1 == p2) printf (" Nécessairement *p1 == *p2 ");
p2 = &j; /* *p2 est la variable j */
if (*p1 == *p2) printf (" Ne signifie pas p1 == p2 !!! ");
}
115
Pointeurs et typage
• Typage d'un pointeur
- un pointeur est typé par le type de l'objet pointé
int * pi1, * pi2; /* pi1 et pi2 sont de type pointeur sur entier */
char * pc; /* pc est de type pointeur sur caractère */
• Affectation entre pointeurs
- l'affectation p1 = p2 est correcte si p1 et p2 sont de même type
- pi1 = pi2; /* affectation correcte */
- pi1 = pc; /* affectation erronée !!! */
116
Passage de paramètres par valeur
#include <stdio.h>
int carre ( )
{
return (x * x);
}
main ()
{
int i = 3;
int car;
car = carre ( );
printf ("%d", car);
}
main Carre
i
i
car
car
i
3
copie
valeur
retour
valeur
avant
appel
de carre
appel
de carre
fin de
l'exéc.
de carre
3 3
3
9 9
car
x
int x
i
117
Passage de paramètres par adresse
#include <stdio.h>
void raz ( )
{
*ip = 0;
}
main ()
{
int i = 3;
raz ( );
printf ("%d", i);
}
main Raz
i
i
i
3
copie
avant
appel
de raz
appel
de raz
fin de
l'exéc.
de raz
3
int *ip
&i
&i ip
adresse
0
*ip
118
Synthèse sur le passage de paramètres
• Passage par valeur
- la valeur du paramètre effectif est recopiée dans le paramètre for
- le paramètre effectif est la valeur d'une expression
- le paramètre effectif ne peut pas être modifié par la fonction
• Passage par adresse
- l'adresse du paramètre effectif est recopiée dans le paramètre form
- le paramètre effectif est une variable
- le paramètre effectif peut être modifié par la fonction
- un tableau est toujours passé par adresse
119
Pointeurs et tableaux
• Identificateur de tableau
le nom d'un tableau est une constante dont la valeur
est l'adresse du premier élément du tableau
0 1 2
ou &t[0]
• Opérateurs "+" et "-" sur les pointeurs
int *p;
p = &t[1]; ==> p+1 pointe sur t[2] et p-1 pointe sur t[0]
• Equivalence tableau / pointeur
int t[N]; ==> &t[k] equivaut à t+k pour k dans 0..N-1
t
int t[3];
120
Tableau en paramètre de fonction
• Prototype d'une fonction triTableau
void triTableau (int tab[], int n);
• Appel de la fonction triTableau
int t[3] = {4, 7, 2};
triTableau (t,3);
• Passage du tableau t en paramètre
à l'appel de triTableau, l'argument tab est initialisé avec &t[0]
==> un tableau est toujours passé par adresse
/* tab est une variable
de type pointeur sur entier */
/* t est une constante de type pointeur sur entier */
121
Pointeurs sur tableaux
int t1[3] = {4, 6, 1};
int *p1 = t1;
int t2[3] = {2, 7, 9};
int *p2 = t2;
4 6 1
2 7 9
p1
p2
0 1 2
p2 = p1;
4 6 1
2 7 9
p1
p2
0 1 2
4 1
2 7 9
p1
p2
0 1 2
- 5
*(p2+1) = - 5 ;
==> modification de t1[1] !!!
t1
t2
t1
t2
t2
t1
122
Pointeurs et chaînes de caractères
• Constantes chaînes de caractères
- "ada", "pascal" sont des constantes littérales
- une constante chaîne de caractères est implantée comme
une séquence de caractères, terminée par le caractère '0'
- sa valeur est l'adresse de son premier caractère
- son type est pointeur sur caractère
• Pointeurs sur chaîne de caractères
char * ch = "ada";
• Tableaux de caractères
char tc[] = {'a', 'd', 'a', '0'};
a a
d 0
non modifiable !!
ch
a a
d 0
modifiable !!
tc
non modifiable !!
modifiable !!
123
Allocation dynamique de mémoire
• Principe de l'allocation dynamique
- le programmeur alloue demande au système d'exploitation de lu
allouer de la mémoire durant l'exécution
- les variables allouées dynamiquement sont stockées
dans une zone mémoire dédiée appelée tas (heap)
• Fonctions d'allocation
- fournies par la bibliothèque standard : fichier <stdlib.h>
- allocation d'une zone mémoire : fonction malloc
- désallocation d'une zone mémoire : fonction free
124
La fonction malloc
• L'opérateur sizeof
- donne la taille en octets d'un type ou d'une expression
- sizeof (int) vaut 4, sizeof (char) vaut 1, ...
- int i; => sizeof i vaut 4
• Allocation d'une variable de type simple
int * ip;
ip = malloc ( sizeof (int) ); /* ou malloc ( sizeof *ip )*/
• Allocation d'une variable structurée
typedef struct {float re,im;} Complexe;
Complexe * cp;
cp = malloc ( sizeof (Complexe) ); /* ou malloc ( sizeof *cp ) */
125
La fonction free
• Contexte initial
z *z
z->re ou (*z).re z->im ou (*z).im
0.0 1.0
Complexe * z;
z = malloc (sizeof(Complexe));
z->re = 0.0; z->im = 1.0;
• Suppression d'une variable dynamique
free (z);
z
• Attention danger !!!
- après free(z), une référence à *z est une erreur !
- suppression d'une variable dynamique désignée par n pointeurs !
?
126
Les allocations mémoire en C
• Allocation statique
- variable externe à une fonction (variable globale)
- variable locale à une fonction mais déclarée static
- allocation statique à la compilation
- initialisation par défaut à 0
• Allocation automatique
- variable interne à une fonction (variable locale)
- allocation automatique à l'exécution dans la pile (stack)
- initialisation indéfinie
• Allocation dynamique avec malloc
- variable dynamique
- allocation dynamique à l'exécution dans le tas (heap)
- initialisation indéfinie
Les variables fichiers
Le type fichier
• On manipule les fichiers par l’intermédiaire de
structures FILE décrites dans stdio.h
FILE *monFichier;
– Nom physique
– Type d’accès(binaire ou formaté … distinction floue)
– Adresse du buffer
– Position dans le fichier
– Indicateur d’erreur
• Trois fichiers/flux standard, ouvert par défaut:
stdin, stdout et stderr
Ouverture/Fermeture d’un fichier
• Faire le lien entre le nom physique (chaîne de caractère,
chemin absolu ou relatif) et le nom logique (nom du
pointeur)
• Ouvrir dans le mode choisi (binaire, écriture, écraser,
lecture,…)
• Se positionner au début de fichier
fich = fopen(nom_physique, mode);
TESTER si le fichier a été ouvert (pas null).
fopen(nom, ``r``); →0 si le fichier n’existe pas.
fopen(nom, ``w``); →0 si le chemin d’accès est faux.
fclose(fich);
Mode d’ouverture
• r ouverture d’un fichier texte en lecture
• w crée un fichier texte en écriture, écrase le contenu
précédent si le fichier existait.
• a ajoute: ouvre ou crée un fichier texte et se positionne en
écriture à la fin du fichier.
• r+ ouvre un fichier en mode mise à jour (lecture et
écriture)
• w+ crée un fichier texte en mode mise à jour, écrase le
contenu précédent si le fichier existait.
• a+ ajoute, ouvre ou crée un fichier texte en mode mise à
jour et se positionne en écriture à le fin du fichier.
Exemple
FILE *fich;
char nom[100];
printf(``nom du fichier à lire : n``);
scanf(``%s``,nom);
if( (fich=fopen(nom, ``r``)) ==NULL)
exit(1);
Les entrées/sorties caractère
• int getc(FILE *); int fgetc(FILE *); int getchar();
• int putc(FILE *); int fputc(FILE *); int putchar();
Exemple:
void main(void){
int c;
FILE *fich;
fich = fopen(``données``, ``r``);
do{
c = getc(fich);
} while(c= = EOF);
}
Autre test sortie: int feof(FILE *) retourne pas zéro si EOF
Les entrées/sorties formatées
• Les fonctions fprintf() et fscanf() s’utilisent
exactement de la même façon que printf et scanf,
il suffit d’ajouter un paramètre pointeur de fichier:
FILE *fichier;
fichier = fopen(nomFichier, ``w``);
int x=25;
fprintf(fichier, ``%dn``,x);
Qui pourra être lu par: fscanf(fichier,``%d``,&a);
Les entrées/sorties binaires
bufferisées
• Sur fichiers ouverts en binaire fich = fopen(monFichier,
``rb``);
• size_t fread(void *ptr, size_t size, unsigned int n, FILE
*stream);
• size_t fwrite(void *ptr, size_t size, unsigned int n, FILE
*stream);
• Principe: écrire directement la représentation machine des
variables (c’est-à-dire de leur contenu mémoire)
• Exemple: short x =1024; 00000100 00000000
fprintf(fich,``%d``,x) écrira les 4 caractères ‘1’, ‘0’, ‘2’ et
‘4’ dans le fichier texte
fwrite(&x, sizeof(x), 1, fich) écrira les deux octets dans le
fichier
Les entrées/sorties binaires
bufferisées(2)
• Avantages: stockage réduit et
lecture/écriture efficace. (une copie de la
mémoire)
• Inconvénients: non portable (taille des
objets diff.), non lisibles par éditeurs de
textes. (créer des programmes scanf/fwrite
et fread/printf C pour les convertir)
Fonction de parcours du fichier
int fseek(FILE *flux, long int offset, int flag);
Modifie la position du pointeur de fichier (lieu
du prochain accès).
Flag:
– SEEK_SET début de fichier
– SEEK_CUR relativement à la position courante
– SEEK_END fin du fichier
Traitement des erreurs de gestion de
fichier
Accès à des fichiers est source d’erreurs
multiples:
• Lors de l’ouverture (fichier inexistant, droits
restrictifs, manque de place, erreur
matérielle)
• Rencontre d’une fin de fichier
• Manque de place sur l’unité concernée
• Destruction de la structure FILE
• Mauvaise opération sur pointeur de fichier
Détection des erreurs
• Seule l’erreur matérielle est détecté par le système,
toute les autres ne provoquent PAS l’arrêt du
programme: il faut les traiter.
• Un indicateur ferror peu efficace (oui/non)
int ferror(FILE *);
• Un indicateur errno peu fiable
• Détection de la fin de fichier avec feof (il faut
avoir lu la fin de fichier pour la reconnaître)
• Consulter les valeurs de retour des fonctions
Détection des erreurs
• nb_ecrit = fwrite(…,nblocs,fich);
Si nb_ecrit == nblocs OK, si inf: erreur
• nb_lu = fread(…, nblocs,fich);
Si nb_lu == nblocs et !feof, OK
Si nb_lu est inf. à nblocs et !feof, pb materiel
Si nb_lu == 0 et feof, fin de fichier normal
Si nb_lu !=0 et eof, fin de fichier anormal
Détection des erreurs
• ncar = fprintf(fich, …); si negatif alors pb
• nb_lu = fsanf (fich,…);
Si nb_lu == nb_attendu et !feof, OK
Si nb_lu est inf. à nb_attendu et !feof, pb materiel
Si nb_lu == EOF et feof, fin de fichier normal
Si nb_lu !=EOF et eof, fin de fichier anormal
Détection des erreurs
• c_ecrit = fputc(…,fich);
c_ecrit != EOF, l’écriture s’est bien déroulé
sinon, erreur d’écriture par manque de place ou
erreur matériel.
• ret = fgetc(fich);
ret != EOF et !feof lecture normale
ret == EOF et !feof pb matériel
feof fin de fichier normale

Contenu connexe

Similaire à Cours programmation en langage C.pdf

Formation python
Formation pythonFormation python
Formation python
Thierry Gayet
 
Ch02
Ch02Ch02
Ch02
yarsenv47
 
Initiation r
Initiation rInitiation r
Chap 1 Initiation.pptx
Chap 1 Initiation.pptxChap 1 Initiation.pptx
Chap 1 Initiation.pptx
olfaharrabi2
 
Cours langage c
Cours langage cCours langage c
Cours langage c
coursuniv
 
CPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
SiratiSoufiane
 
Technologies du Web - Architectures matérielles et logicielles
Technologies du Web - Architectures matérielles et logiciellesTechnologies du Web - Architectures matérielles et logicielles
Technologies du Web - Architectures matérielles et logicielles
Frédéric Simonet
 
Chapitre 1 (algorithme)
Chapitre 1 (algorithme)Chapitre 1 (algorithme)
Chapitre 1 (algorithme)mahbouba
 
OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...
OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...
OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...
Pôle Systematic Paris-Region
 
Formation python
Formation pythonFormation python
Formation python
j_lipaz
 
Info smpc2 part1
Info smpc2 part1Info smpc2 part1
Info smpc2 part1
mostafadess
 
Ch2-Notions de base & actions élémentaires.pdf
Ch2-Notions de base & actions élémentaires.pdfCh2-Notions de base & actions élémentaires.pdf
Ch2-Notions de base & actions élémentaires.pdf
FadouaBouafifSamoud
 
fortran 2.pdf
fortran 2.pdffortran 2.pdf
fortran 2.pdf
McWalidBensaid
 
Numeration et codage_de_linfo
Numeration et codage_de_linfoNumeration et codage_de_linfo
Numeration et codage_de_linfoyarsenv47
 
Tp1 matlab
Tp1 matlab Tp1 matlab
Tp1 matlab
Wajdi Ben Helal
 
Chap1_Entrees_Sorties.pptx
Chap1_Entrees_Sorties.pptxChap1_Entrees_Sorties.pptx
Chap1_Entrees_Sorties.pptx
BelhassenGuettat2
 
Algorithmique&Langage C-Partie1 BTS.pptx
Algorithmique&Langage C-Partie1 BTS.pptxAlgorithmique&Langage C-Partie1 BTS.pptx
Algorithmique&Langage C-Partie1 BTS.pptx
Facebokma
 
Debuter en Python.ppt
Debuter en Python.pptDebuter en Python.ppt
Debuter en Python.ppt
SofienBoutaib
 

Similaire à Cours programmation en langage C.pdf (20)

Chapitre 2
Chapitre 2Chapitre 2
Chapitre 2
 
Formation python
Formation pythonFormation python
Formation python
 
Ch02
Ch02Ch02
Ch02
 
Initiation r
Initiation rInitiation r
Initiation r
 
Chap 1 Initiation.pptx
Chap 1 Initiation.pptxChap 1 Initiation.pptx
Chap 1 Initiation.pptx
 
Cours langage c
Cours langage cCours langage c
Cours langage c
 
CPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CPP PTT DE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
 
Technologies du Web - Architectures matérielles et logicielles
Technologies du Web - Architectures matérielles et logiciellesTechnologies du Web - Architectures matérielles et logicielles
Technologies du Web - Architectures matérielles et logicielles
 
Chapitre 1 (algorithme)
Chapitre 1 (algorithme)Chapitre 1 (algorithme)
Chapitre 1 (algorithme)
 
OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...
OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...
OSIS18_IoT: L'approche machine virtuelle pour les microcontrôleurs, le projet...
 
Formation python
Formation pythonFormation python
Formation python
 
Info smpc2 part1
Info smpc2 part1Info smpc2 part1
Info smpc2 part1
 
Ch2-Notions de base & actions élémentaires.pdf
Ch2-Notions de base & actions élémentaires.pdfCh2-Notions de base & actions élémentaires.pdf
Ch2-Notions de base & actions élémentaires.pdf
 
fortran 2.pdf
fortran 2.pdffortran 2.pdf
fortran 2.pdf
 
Tp introduction java
Tp introduction javaTp introduction java
Tp introduction java
 
Numeration et codage_de_linfo
Numeration et codage_de_linfoNumeration et codage_de_linfo
Numeration et codage_de_linfo
 
Tp1 matlab
Tp1 matlab Tp1 matlab
Tp1 matlab
 
Chap1_Entrees_Sorties.pptx
Chap1_Entrees_Sorties.pptxChap1_Entrees_Sorties.pptx
Chap1_Entrees_Sorties.pptx
 
Algorithmique&Langage C-Partie1 BTS.pptx
Algorithmique&Langage C-Partie1 BTS.pptxAlgorithmique&Langage C-Partie1 BTS.pptx
Algorithmique&Langage C-Partie1 BTS.pptx
 
Debuter en Python.ppt
Debuter en Python.pptDebuter en Python.ppt
Debuter en Python.ppt
 

Dernier

Conseils pour Les Jeunes | Conseils de La Vie| Conseil de La Jeunesse
Conseils pour Les Jeunes | Conseils de La Vie| Conseil de La JeunesseConseils pour Les Jeunes | Conseils de La Vie| Conseil de La Jeunesse
Conseils pour Les Jeunes | Conseils de La Vie| Conseil de La Jeunesse
Oscar Smith
 
Edito-B1-francais Manuel to learning.pdf
Edito-B1-francais Manuel to learning.pdfEdito-B1-francais Manuel to learning.pdf
Edito-B1-francais Manuel to learning.pdf
WarlockeTamagafk
 
Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...
Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...
Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...
mrelmejri
 
Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...
Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...
Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...
cristionobedi
 
Burkina Faso library newsletter May 2024
Burkina Faso library newsletter May 2024Burkina Faso library newsletter May 2024
Burkina Faso library newsletter May 2024
Friends of African Village Libraries
 
Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...
Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...
Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...
M2i Formation
 
Iris van Herpen. pptx
Iris         van         Herpen.      pptxIris         van         Herpen.      pptx
Iris van Herpen. pptx
Txaruka
 
Newsletter SPW Agriculture en province du Luxembourg du 12-06-24
Newsletter SPW Agriculture en province du Luxembourg du 12-06-24Newsletter SPW Agriculture en province du Luxembourg du 12-06-24
Newsletter SPW Agriculture en province du Luxembourg du 12-06-24
BenotGeorges3
 
Iris van Herpen. pptx
Iris         van        Herpen.      pptxIris         van        Herpen.      pptx
Iris van Herpen. pptx
Txaruka
 
Iris van Herpen. pptx
Iris            van        Herpen.     pptxIris            van        Herpen.     pptx
Iris van Herpen. pptx
Txaruka
 
Cycle de Formation Théâtrale 2024 / 2025
Cycle de Formation Théâtrale 2024 / 2025Cycle de Formation Théâtrale 2024 / 2025
Cycle de Formation Théâtrale 2024 / 2025
Billy DEYLORD
 
Procédure consignation Lock Out Tag Out.pptx
Procédure consignation  Lock Out Tag Out.pptxProcédure consignation  Lock Out Tag Out.pptx
Procédure consignation Lock Out Tag Out.pptx
caggoune66
 

Dernier (12)

Conseils pour Les Jeunes | Conseils de La Vie| Conseil de La Jeunesse
Conseils pour Les Jeunes | Conseils de La Vie| Conseil de La JeunesseConseils pour Les Jeunes | Conseils de La Vie| Conseil de La Jeunesse
Conseils pour Les Jeunes | Conseils de La Vie| Conseil de La Jeunesse
 
Edito-B1-francais Manuel to learning.pdf
Edito-B1-francais Manuel to learning.pdfEdito-B1-francais Manuel to learning.pdf
Edito-B1-francais Manuel to learning.pdf
 
Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...
Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...
Impact des Critères Environnementaux, Sociaux et de Gouvernance (ESG) sur les...
 
Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...
Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...
Formation Intelligence Artificielle pour dirigeants- IT6-DIGITALIX 24_opt OK_...
 
Burkina Faso library newsletter May 2024
Burkina Faso library newsletter May 2024Burkina Faso library newsletter May 2024
Burkina Faso library newsletter May 2024
 
Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...
Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...
Formation M2i - Onboarding réussi - les clés pour intégrer efficacement vos n...
 
Iris van Herpen. pptx
Iris         van         Herpen.      pptxIris         van         Herpen.      pptx
Iris van Herpen. pptx
 
Newsletter SPW Agriculture en province du Luxembourg du 12-06-24
Newsletter SPW Agriculture en province du Luxembourg du 12-06-24Newsletter SPW Agriculture en province du Luxembourg du 12-06-24
Newsletter SPW Agriculture en province du Luxembourg du 12-06-24
 
Iris van Herpen. pptx
Iris         van        Herpen.      pptxIris         van        Herpen.      pptx
Iris van Herpen. pptx
 
Iris van Herpen. pptx
Iris            van        Herpen.     pptxIris            van        Herpen.     pptx
Iris van Herpen. pptx
 
Cycle de Formation Théâtrale 2024 / 2025
Cycle de Formation Théâtrale 2024 / 2025Cycle de Formation Théâtrale 2024 / 2025
Cycle de Formation Théâtrale 2024 / 2025
 
Procédure consignation Lock Out Tag Out.pptx
Procédure consignation  Lock Out Tag Out.pptxProcédure consignation  Lock Out Tag Out.pptx
Procédure consignation Lock Out Tag Out.pptx
 

Cours programmation en langage C.pdf

  • 4. 4 Unité élémentaire = système physique bistable (Bit) (2 états) ∀ l'information = {0, 1} nombre, texte, image, son représentation des informations en Mémoire
  • 5. 5 décimal binaire 0 0 2 10 3 11 7 111 Nombre Exemples de représentation
  • 6. 6 Un octet = 8 bits ex : 1 0 1 1 0 1 1 0 Combien d'objets distincts peut-on représenter avec un octet ? Octet ?
  • 7. 7 1 bit 1 octet 1 Kilo octet (Ko) = 1024 octets 1 Mega octet (Mo) = 1024 Ko = 1024 * 1024 octets 1 giga octet (Go) = 1024 Mo Volume mémoire
  • 8. 8 1 octet 1 octet 1 octet 1 octet 1 octet 1 octet Organisation de l’information en mémoire Chaque octet de la mémoire est repéré par une adresse Adresse Le nombre d’octet occupés par une information dépend du type de cette information: entier, réel, Caractère, chaîne de caractères
  • 9. 9 32 espaces 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ` 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W 88 X 89 Y 90 Z 91  92 93 ] 94 ^ 95 — 96 - 97 a 98 b 99 c 100 d 101 e 102 f 103 g 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x 121 y 122 z 123 { 124  125 } 126 ~ 127 Représentation des caractères sur un octet (ASCII)
  • 10. 10 Instructions Algorithme Programme exécutables par la machine langage de programmation compilateur Algorithmes - Programmes
  • 11. 11 "Une suite finie de règles à appliquer dans un ordre déterminé à un nombre fini de données pour arriver, en un nombre fini d'étapes, à un certain résultat, et cela indépendamment des données". Algorithme
  • 12. 12 langage machine le seul compréhensible par la machine langage assembleur très proche du langage machine, mais plus explicite langage évolué proche de la description (3ème génération) des algorithmes C, FORTRAN, PASCAL langage facilite la recherche 4è génération d'information dans les bases de données (SQL) Langages de programmation ? Bas niveau Haut niveau
  • 13. 13 Langage C Conception et description d'un algorithme Programme C programme objet exécutable Langage C compilation
  • 14. 14 programme C COMPILATEUR programme objet Editeur de liens programme exécutable données résultat Exécution d'un programme
  • 15. 15 Historique Pour développer une version portable du système d'exploitation UNIX, en 1972 dans les 'Bell Laboratories' Dennis M. Ritchie a conçu un langage de programmation structuré, mais très 'près' de la machine: c’est la naissance du langage C. K&R-C En 1978, le duo Brian W. Kernighan / Dennis M. Ritchie a publié la définition classique du langage C (connue sous le nom de standard K&R- C ) dans un livre intitulé 'The C Programming Language'. ANSI-C En 1983, le 'American National Standards Institute' (ANSI) chargeait une commission de mettre au point 'une définition explicite et indépendante de la machine pour le langage C', qui devrait quand même conserver l'esprit du langage. Le résultat était le standard ANSI-C
  • 16. 16 Avantages Le grand succès du langage C s'explique par les avantages suivants; C est un langage: (1) universel : C n'est pas orienté vers un domaine d'applications spéciales, comme par exemple FORTRAN (applications scientifiques et techniques) ou COBOL (applications commerciales ou traitant de grandes quantités de données). (2) compact : C est basé sur un noyau de fonctions et d'opérateurs limité, qui permet la formulation d'expressions simples, mais efficaces. (3) moderne : C est un langage structuré, déclaratif et récursif; il offre des structures de contrôle et de déclaration comparables à celles des autres grands langages de ce temps (FORTRAN, ALGOL68, PASCAL).
  • 17. 17 4) près de la machine : comme C a été développé en premier lieu pour programmer le système d'exploitation UNIX, il offre des opérateurs qui sont très proches de ceux du langage machine et des fonctions qui permettent un accès simple et direct aux fonctions internes de l'ordinateur (p.ex: la gestion de la mémoire). (5) rapide : comme C permet d'utiliser des expressions et des opérateurs qui sont très proches du langage machine, il est possible de développer des programmes efficients et rapides. (6) indépendant de la machine : bien que C soit un langage près de la machine, il peut être utilisé sur n'importe quel système en possession d'un compilateur C. Au début C était surtout le langage des systèmes travaillant sous UNIX, aujourd'hui C est devenu le langage de programmation standard dans le domaine des micro-ordinateurs.
  • 18. 18 (7) portable : en respectant le standard ANSI-C, il est possible d'utiliser le même programme sur tout autre système (autre hardware, autre système d'exploitation), simplement en le recompilant. (8) extensible : C ne se compose pas seulement des fonctions standard; le langage est animé par des bibliothèques de fonctions privées ou livrées par de nombreuses maisons de développement.
  • 19. 19 Présentation du langage  Premières notions Les types de base Les entiers, les réels (sous ensemble fini des rationnels), et les caractères. Les entiers: Définition Description Dom min Dom max Nbre octets short int Entier court -32768 +32767 2 octet int Entier standard -32768 +32767 2 octet long int Entier long -2147483648 +21474836487 4 octet
  • 20. 20 Définition Description Dom min Dom max Nbre octets unsigned short int Entier court 0 65535 2 octet unsigned int Entier standard 0 65535 2 octet unsigned long int Entier long 0 4294967295 4 octet Il est possible de travailler avec un entier non signé Les caractères Définition Description Dom min Dom max Nbre octets unsigned char Caractère non signé 0 255 1 octet char caractère 0 255 1octet signed char Caractère signé -128 127 1 octet
  • 21. 21 Les nombres en virgule flottante <+|-> <mantisse> * 10<exposant> <+|-> est le signe positif ou négatif du nombre <mantisse> est un décimal positif avec un seul chiffre devant la virgule <exposant> est un entier relatif En C, nous avons le choix entre trois types de rationnels: float, double et long double. Dans le tableau ci-dessous, vous trouverez leurs caractéristiques: Définition Description mantisse Dom min Dom max Nbre octets float simple 6 -3.4 * 10-38 3.4 * 1038 4 octet double double 15 -1.7 * 10-308 1.7 * 10308 8 octet long double Long double 19 -3.4 * 10-4932 1.1 * 104932 10 octet
  • 22. 22 2. Les variables Emplacement mémoire dans lequel est codé une information que l’on peut modifier et utiliser grâce à un identificateur. Toute variable doit être déclarée avant d’être utilisée Syntaxe: <type> < identificateur> Identificateur: composé de chiffres, de lettres et du caractère _ ; son premier caractère ne doit pas être un chiffre. Les majuscules et les minscules ne sont pas équivalentes. Ainsi : le_langage_C et le_lAngae_C sont deux identificateurs distincts. Exemple: unsigned long int le nombre; int I_entier; double le_reel; unsigned char le_caractère;
  • 23. 23 3. Les constantes Contrairement à une variable, une constante ne peut être modifiée. Les constantes entières Elles peuvent être représentées selon trois systèmes de numération: décimale, octale(précédée de 0) et héxadécimale (précédée de 0x ou 0X) Base décimale Base octale Base héxadécimale Représentation binaire 100 0144 0X64 1100100 255 0377 0xff 11111111 65536 0200000 0X10000 10000000000000000
  • 24. 24 Selon sa valeur, une constante entière est codé soit comme: un entier, un entier long. On peut même forcer le codage en entier long en ajoutant la lettre l ou L. les constantes non signées s’écrivent avec un u ou U à la fin. Exemples: 0XAL, 5u, 6l, 10uL, 041lU, 25UL, 0x78ul Les constantes en virgule flottante •En notation décimale: <partie entière>.<partie fractionnaire> Exemples: 3.14159, 1000.001, 2001.007, .125 •En notation scientifique: <partie entière>.<partie fractionnaire>e[signe]<nombre entier> <partie entière>.<partie fractionnaire>E[signe]<nombre entier> Exemples: 3.14159e0, 0.314159E+1, 314.159e-2
  • 25. 25 Les constantes caractères Une constante caractère s’écrit en encadrant le caractère par deux apostrophes. Exemple: 'A', '$', 'a', 'o', '0', '1', etc… Il est possible de remplacer le caractère, par exemple A, par son code ASCII (65) exprimé en octale précédé par ou héxadécimale précédé par x. Les constantes 'A' , '101' et 'x41' sont identiques. Code décimal caractère séquence signification 7 BEL a Sonnette 8 BS b Retour arrière 9 HT t Tab horizontale 10 NL n Changement de ligne 11 VT v Tab verticale 12 FF f Saut de page 13 RC r Retour chariot
  • 26. 26 t o u l e s m o n d e Les constantes chaîne de caractères Une constante chaîne de caractères est une suite finie de caractères, délimitée par des guillemets. Une chaîne se termine impérativement par le caractère non affichable NULL (code ASCII: zéro) qui est ajouté automatiquement par le compilateur. Exemple: en mémoire la chaîne "tous le monde" est représentée par: 0 Attention ne confondons pas le caractère 'a' et la chaîne "a" qui, elle comprend deux caractère 'a' et '0'.
  • 27. 27 Utilisation des constantes: •Soitdirectement: I_entier = 20; (on affecte 20 à la variable I_entier), •Soit en définissant un nom symbolique à la constante par: # define MAX 20 Et I_entier = MAX; La directive #define s'adresse au préprocesseur; celui-ci remplace toutes les occurrences MAX par 20 et ceci avant la compilation. Exemples: #define MESSAGE ”le langage C ” #define PI 3.14159 •Soit en utilisant un identificateur déclaré avec le mot-clé const Syntaxe: const <type> <identificateur> = <valeur>; Exemples: const double pi =3.14159; const int max = 20;
  • 28. 28 4. Les opérateurs Les opérateurs, les variables et les constantes permettent de construire des expressions. En C, une expression a toujours un type et une valeur. Une instruction élémentaire est obtenue en ajoutant à une expression le caractère ; Les opérateurs arithmétiques Ce sont les opérateurs + (addition), - (soustraction), * (multiplication), / (division) et % (reste de la division entière). Syntaxe: <expression numérique> op <expression numérique> Où op est l’un des opérateurs +, -, *. < expression> / < expression> où l’une des deux expression est de type flottant. Le résultat est de type flottant.
  • 29. 29 <expression entière> / <expression entière> . Le résultat est entier <expression entière> % <expression entière> . Le résultat est entier Exemples: 7 * 5 et 7.0 * 5 sont respectivement de type entier et de type réel. Les expressions 7.0 / 5, 7 / 5 et 7 % 5 valent respectivement 1.4, 1 et 2. Notez bien qu’il y a deux divisions et un seul symbole. L’affectation Syntaxe: <variable> = < expression> Le résultat de l’expression est convertit, si cela a un sens, au type de la variable. Déclarons trois variables: int I_entier, le_nombre; double le_reel; Les instructions I_entier = 3 ; et le_reel = 3.14 sont des instructions d’affectation. L’affectation en cascade le_nombre = I_entier = 3 ; est correcte.
  • 30. 30 L’incrémentation, la décrémentation Syntaxe: <variable> op ou op <variable> où op est l’un des opérateurs ++ ou – L’expression le_nombre = le nombre + 1 peut être remplacée par le_nombre++ ou ++le_nombre. Attention la valeur de l’expression le_nombre++ est égale à la valeur de nombre avant l’incrémentation alors que ++le_nombre a pour valeur le_nombre après l’incrémentation. Ainsi la séquence d’instructions Le_nombre = 3; I_entier = le_nombre++; le_reel = ++le_nombre A pour résultat d’affecter 3 à I_entier et 5 à le_reel, le_nomre contenant en définitive 5. L’opérateur de décrémentation a le même comportement que le précédent. Ainsi l’instruction le_reel--; diminue de 1 le contenu de le_reel.
  • 31. 31 Les affectations généralisées: +=, -=, *=, /=, %=, etc L’expression I_entier = I_entier + 2 est équivalente à I_entier += 2 L’instruction I_entier = I_entier + le_nombre; est équivalente à I_entier += le_nombre; La syntaxe générale est: <variable> op <expression> où op est l’un des opérateurs +=, -=, *=, /=, %= Exemple : le_nombre contenant 5. Après la séquence : I_entier = 8; I_entier += le_nombre; I_entier contient 13. Les opérateurs relationnels: égal à (==), différent !=, strictement supérieur à (>), strictement inférieur à (<), supérieur à (>=) et inférieur à (<=).
  • 32. 32 La syntaxe est : <variable> op <expression> où op est l’un des opérateurs ==, !=,<, >, <=, >=. Exemples: si I_entier contient 3 , le_nombre 2 et le_reel 3. Les expressions I_entier==le_nombre, I_entier >4, le_reel<=le_nombre sont fausses et valent donc 0. De même les expressions I_entier != 5, le_reel == I_entier, le_nombre < 14 sont vraies et valent 1. Les opérateurs logiques: Ce sont les connecteurs ET et OU ainsi que la négation; ils sont représentés respectivement pa && , ||, et !. La syntaxe: <expression numérique> op <expression numérique> où op est l’un des opérateurs && , ||. != <expression numérique>
  • 33. 33 Les opérateurs de traitement de bits: complémentation ~ dans la représentation binaire, tous les bits à 1 sont mis à 0 et réciproquement. Syntaxe: ~ <expression entière> Exemple: la représentation de 10 est : 0000000000001010 la représentation de ~10 est : 1111111111110101 les opérateurs de traitement de bits: syntaxe : <expression entière> OP <expression entière> OP est l ’un des opérateurs &, | ou ^ & 0 1 0 0 0 1 0 1 | 0 1 0 0 1 1 1 1 ^ 0 1 0 0 1 1 1 0
  • 34. 34 Exemple: la représentation de binaire de 65 est : 0000000001000001 la représentation de binaire de 9 est : 0000000000001001 la représentation de binaire de 65 & 9 est : 0000000000000001 la représentation de binaire de 65 | 9 est : 0000000001001001 la représentation de binaire de 65 ^ 9 est : 0000000001001000 les opérateurs de décalage: ils permettent de décaler vers la droite (>>) ou vers la gauche (<<) tous les bits d ’un nombre entier. Syntaxe: <expression entière> OP <expression entière> OP est l ’un des opérateurs << ou >> Exemple: la représentation de binaire de 65 <<9 est : 1000001000000000 la représentation de binaire de 65 >>3 est : 0000000000001000
  • 35. 35 Les opérateurs & et sizeof(). L ’opérateur & permet de connaître l ’adresse ( l ’emplacement mémoire) d ’une variable. Exemple : & I_entier désigne l ’endroit où est la variable I_entier. Pour connaître la taille on utilise l ’opérateur sizeof(). Syntaxe : & <variable> sizeof ( <variable>) sizeof (<type>) & I_entier I_entier
  • 36. 36 L ’opérateur conditionnel syntaxe : <expressionC> ? <expression1> : <expression2> la valeur du résultat est la valeur de l ’expression1 si l ’expressionC est différente de zéro et expression2 sinon. Exemple : l ’expression (I_entier == 8 ? I_entier / 2 : 7) a pour valeur 4 si I_entier vaut 8 et 7 dans le cas contraire. L ’opérateur de coercition syntaxe : (<type>) <expression> il force la conversion du type de la valeur d ’une expression. Exemple : 012 est de type entier et (double)012 est de type double si le_reel est de type float, (unsigned long int)le_reel est de type unsugned long int; la valeur étant correctement arrondie.
  • 37. 37 La virgule est un opérateur il permet de construire une expression composée. Syntaxe : <expression1> , <expression2> l ’expression1 puis l ’expression2 sont évaluées. Le résultat a pour type et a pour valeur ceux de l ’expression 2. Exemple : après l ’instruction : le_nombre = (I_entier = 4 , I_entier ++, I_entier * 3); le_nombre vaut 15. L ’opérateur unaire - est l ’opposé par symétrie, l ’opérateur + est défini. Exemple : +5, -5, +I_entier, -I_entier.
  • 38. 38 Opérateur Niveau Symbole Associativité De structure Unaire Multiplicatif Additif De décalage D’inégalité D’égalité De bit à bit De bit à bit De bit à bit Conjonction Disjonction Conditionnel Exp composée 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ( ) . -> [ ] ~ ! ++ -- - + (<type>) (indirection), & sizeof * / % + - >> << < <= > >= == != & ^ | && || ? : = += -= *= /= %= &= ^= |= <<= >>= , De gauche vers droite De droite vers gauche De gauche vers droite De gauche vers droite De gauche vers droite De gauche vers droite De gauche vers droite De gauche vers droite De gauche vers droite De gauche vers droite De gauche vers droite De gauche vers droite De droite vers gauche De droite vers gauche De gauche vers droite Tableau récapitulatif des opérateurs
  • 39. 39 Les fonctions Définition : les fonctions sont les sous-programmes du C; elles permettent de regrouper des instructions et de lancer leur exécution grâce à un identificateur. Syntaxe : [type] <identificateur>(liste des paramètres formels]) { . . . < corps de la fonction> . . . } /* fin de la fonction
  • 40. 40 Remarques : le type d ’une fonction est déterminé par le type du résultat qu ’elle retourne. Une fonction qui ne renvoie pas de valeur au programme appelant est de type void. Le type par défaut d ’une fonction est int. Dès qu’une instruction de retour est rencontrée, l ’exécution de la fonction s ’interrompt. Syntaxe : return; return <expression>; return (<expression>); si la fonction ne contient pas d ’instruction « return », elle s ’achève automatiquement à la fin de son bloc.
  • 41. 41 Exemple : définition : int ce_double (int tel_nb) { int res; res = tel_nb * 2; return res; } /* fin ce_double */ Appel : ce_double(41.125); ou ce_double(le_nb); remarque: l ’argument 41.125 est converti en entier à l ’appel.
  • 42. 42 Déclaration de fonction la déclaration d ’une fonction a pour but d ’avertir le compilateur que cet objet va être utilisé et de lui préciser le type de son résultat et de chacun de ses paramètres formels éventuels. Syntaxe : <type> <identificateur de fonction> (liste des paramètres); Exemple : déclaration du prototype de la fonction précédente: int ce_double (int tel_nb); ou int ce_double (int); Remarque : les prototypes des fonctions des bibliothèques sont déclarés dans des fichiers « en-tête »; il est souhaitable d ’inclure le fichier correspondant lorsque l ’une de ces fonctions est utilisée grâce à la directive de compilation include : # include <stdio.h>
  • 43. 43  Deux fonctions d ’E/S : printf et scanf le prototype de ces fonctions est dans le fichier en-tête stdio.h. la fonction printf pour afficher des résultats on utilise la fonction printf. Syntaxe : printf(<format>, [expression1] [, expression2]. . .) le format est une chaîne de caractères comprenant éventuellement les spécifications de type des expression1, expression2 etc.. à afficher. Exemple : le résultat de l ’instruction printf (" coucou le monde!n"); est coucou le monde! De même printf("le double de %d est %d.n", 8, 16); donne le double de 8 es 16 . Printf("Nous étudions n %s sous n UNIX. n", "le langage C") donne:
  • 44. 44 Nous étudions le langage C sous Unix. Il est possible de fixer la largeur du champ d'affichage pour l'argument. Exemple : printf("valeurs : %5d%10.3fn", 14, 3.1459); donne : 14 3.142 la fonction scanf permet de saisir des données au clavier et de les ranger dans une variable. Syntaxe : scanf (<format>, <adresse d'une variable>) le format est une chaîne réduite à la spécification de données à saisir. Exemple : saisir une données entière et la ranger dans la variable "int" I_entier, scanf("%d", &I_entier);
  • 45. 45 Le type de l’expression Spécificateur d’affichage Spécificateur de saisie Int (écriture décimale) Int (écriture décimale ou octale ou hexadécimale) int (écriture octale) int (écriture hexadécimale) int unsigned short int long int char float (écriture décimale) double (écriture décimale) long double (décimale) float (écriture scientifique) double (scientifique) long double (scientifique) chaîne de caractères %d ou %i %o %x %u %hd ou %ho ou %hx ou %hu %ld ou %lo ou %lx ou %lu %c %f %f %Lf %e ou % E %e ou %E %Le ou %LE %s %d %i %o %x %u (décimale) %hd ou %ho ou %hx ou %hu %ld ou %lo ou %lx ou %lu %c %f %lf %Lf %e %le %Le %s Les spécificateurs de format
  • 46. 46 Structure d'un programme Organisation d'un programme C un programme C se présente sous la forme d'un ou plusieurs fichiers sources. Chaque fichier contient des déclarations et des définitions de variables et de fonctions. La définition d'une fonction contient les déclarations de son type et de la liste (éventuellement vide) de ses paramètres et un bloc. Le programme doit contenir une et une seule fonction de nom main : c'est le point d'entrée du programme. Un bloc commence par le symbole { , contient des déclarations de variables et une suite d'instructions et se termine par le symbole }. Un bloc est appelé aussi "instruction composée".
  • 47. 47 Une instruction est soit une instruction élémentaire (elle doit se terminer par un point virgule), soit un bloc, soit une instruction de contrôle. Notez que si un bloc peut contenir un autre bloc, une fonction ne peut contenir la définition d'une autre fonction. Des directives de compilation apparaissent aussi dans les fichiers sources. Exemples : Le premier programme: void main (void) { printf (" bonjour, tous le monde!n"); } /* main */ ce programme est écrit à l'aide d'un éditeur de texte et sauvegardé sous le nom premier.c. Pour le compiler sous Unix (et aussi Linux) il faut exécuter la commande cc premier.c. Le résultat de la compilation et de l'édition de liens est alors le fichier exécutable a.out
  • 48. 48 Deuxième programme : taille en octets des types de base void main(void) { printf(" la taille d'un entier est : %d octets n",sizeof(int)); printf(" la taille d'un entier court est : %d octets n",sizeof(short int)); printf(" la taille d'un entier long est : %d octets n",sizeof(long int)); printf(" la taille d'un caractère est : %d octet n",sizeof(char)); printf(" la taille d'un "float" est : %d octets n",sizeof(float)); printf(" la taille d'un "double" est : %d octets n",sizeof(double)); printf("et celle d'un "long double" est:%d octetsn",sizeof(long double)); } /* main de taille.c */ compilons: cour_C> cc taille.c
  • 49. 49 Exécutons: cours_C> a.out la taille d'un entier est : 4 octets la taille d'un entier court est : 2 octets la taille d'un entier long est : 4 octets la taille d'un caractère est : 1 octet la taille d'un "float" est : 4 octets la taille d'un "double" est : 8 octets et celle d'un "long double est : 12 octets
  • 50. 50 Troisième exemple: utilisation de scanf void main (void) { float le_flottant; double le_reel; long double le_reel_double; printf("entrez un nombre a virgule:"); scanf("%f",&le_flottant); printf("vous avez tapé %f.n", le_flottant); printf("Affichage du même nombre avec format : %8.3f.n,le_flottant); printf("Entrez un nombre a virgule:"); scanf("%lf",&le_reel); printf("vous avez tapé %f.n", le_reel); printf("Affichage du même nombre avec format : %16.3f.n,le_reel); printf("Entrez un nombre a virgule:"); scanf("%Lf",&le_reel_double); printf("vous avez tapé %Lf.n", le_reel_double); printf("Affichage du nombre avec format :%20.3Lf.n,le_reel_double); } /* main de scanf.c */
  • 51. 51 Cours_C> cc scanf.c cours_C> a.out Entrez un nombre a virgule : 123456.789012345123456789 Vous avez tapé 123456.789062. Affichage du même nombre avec format : 123456.789. Entrez un nombre a virgule : 1234567890123.45123456789 Vous avez tapé 1234567890123.451234. Affichage du même nombre avec format : 1234567890123.451. Entrez un nombre a virgule : 123456789012345.123456789 Vous avez tapé 123456789012345.123456. Affichage du même nombre avec format : 123456789012345.123.
  • 52. 52 Compilation Sous Unix (Linux) la commande cc lance plusieurs programmes: •le préprocesseur •le compilateur •l'assembleur •l'éditeur de liens (qui résout les références externes: ex printf et scanf) Plusieurs syntaxes sont possibles: cc fichier.c l'exécutable a pour nom a.out. cc fichier.c -o fichier l'exécutable a pour nom fichier. cc -c fichier.c compilation sans édition de liens. Le résultat d'assemlage est mis dans le fichier fichier.o. cc fichier1.c fichier2.c fichier3.c -o resultat si le programme est réparti dans plusieurs fichiers sources.
  • 53. 53 Les structures de contrôle
  • 54. 54 Les conditionnelles : if…else (1) if (condition) { instructions; } condition instructions vrai faux
  • 55. 55 Les conditionnelles : if…else (2) if (condition) { instructions1; } else { instructions2; } condition instructions1 vrai faux instructions2
  • 56. 56 Les conditionnelles : if…else (3) int a,b,c,d; if (a<b) { if (c<d) { instructions1; } else { instructions2; } } … … else { instructions3; }
  • 57. 57 Les conditionnelles : switch…case (1) switch (expression) { case constante1: instructions1; break; case constante2: instructions2; break; … … default: instructionsDefaul t; break; }
  • 58. 58 Les conditionnelles : switch…case (2) expression constante1 default instructionsD instructions1 instructions2 ...
  • 59. 59 Les itérations : La boucle for • Syntaxe : for (exp1;exp2;exp3) { instructions; } • Toutes ces expressions influent sur la variable d’itérations qui compte le nombre d’itérations • exp1 : Initialisation • exp2 : Condition d’arrêt • exp3 : Mise à jour
  • 60. 60 Les itérations : La boucle for exp2 exp1 vrai faux instructions exp3 Initialisation Condition d’arrêt Mise à jour
  • 61. 61 Les itérations : La boucle while • Syntaxe : while (condition) { instructions; } Tant que condition vraie exécuter les instructions condition instructions vrai faux
  • 62. 62 Les itérations : La boucle do…while • Syntaxe : do { instructions; } while (condition); Exécuter les instructions tant que condition vraie condition instructions vrai faux
  • 63. 63 Les itérations • Utilisation des différents types de boucles : – for : boucle basée sur une variable d’itération dont on connaît a priori le début et la fin – while ou do…while : boucle dont on ignore a priori quand arrivera la condition de fin • Une boucle doit respecter uniquement ses conditions d’arrêt : pas de break !
  • 64. 64 Les fonctions Définition : les fonctions sont les sous-programmes du C; elles permettent de regrouper des instructions et de lancer leur exécution grâce à un identificateur. Syntaxe : [classe] [type] <identificateur>(liste des paramètres formels]) { . . . < corps de la fonction> . . . } /* fin de la fonction
  • 65. 65 Remarques : •le type d ’une fonction est déterminé par le type du résultat qu ’elle retourne. •Une fonction qui ne renvoie pas de valeur au programme appelant est de type void. •Le type par défaut d ’une fonction est int. •Par défaut la classe d’une fonction est "extern" c-a-d accessible par toutes les fonctions du programme que celles-ci appartiennent ou non au fichier où elle est définie. Par contre, une fonction de classe "static" est locale à son fichier de définition; seules les fonctions du même fichier peuvent l'appeler. Exemple: Considérons les deux fichiers prog_princ.c et fonction1.c
  • 66. 66 cours_C> cat prog_prin.c void main(void) { affiche_le_message(); }/* prog_prin.c*/ cours_C> cat fonction1.c Void affiche_le_message(void) { printf("bonjour tout le monde.n"); }/* fonction1.c*/ cours_C> cc prog_prin.c fonction1.c -o bonjour prog_prin.c: fonction1.c: cours_C>bonjour Bonjour tout le monde.
  • 67. 67 cours_C> cat fonction2.c static void affiche_le_message(void) { printf("bonjour tout le monde.n"); }/* fonction1.c*/ cours_C> cc prog_prin.c fonction2.c -o bonjour prog_prin.c: fonction1.c: Id: Undefined – .affiche_le_message _affiche_le_message _end cours_C> La fonction affiche_le_message est locale au fichier fonction2.c
  • 68. 68 •Dès qu’une instruction de retour est rencontrée, l ’exécution de la fonction s ’interrompt. Syntaxe : return; return <expression>; return (<expression>); si la fonction ne contient pas d ’instruction « return », elle s ’achève automatiquement à la fin de son bloc. •La compilation s'effectue fichier par fichier, le compilateur peut rencontrer une référence à une fonction définie dans un autre fichier: il ignore alors son type; il lui attribue systématiquement le type int. Exemple: Le programme principal main affiche le résultat retourné (3.14159) Par une fonction ce_reel. Ces deux objets sont définis dans des fichiers différents.
  • 69. 69 cours_C> cat p_princ1.c void main(void) { double le_reel; le_reel = ce_reel(); Printf(" valeur de le_reel : %f .n", le_reel); }/* main de p_prin1.c*/ cours_C> cat fonction3.c double ce_reel(void) { return 3.14159; } /* fonct3.c*/ cour_C>cc p_prin1.c fonct3.c -o echange p_prin1.c : fonct.c: cour_C>echange Valeur de le_reel : 1074340345.000000 Pour éviter ce genre d'erreur, il faut appliquer la règle suivante: Tout objet utilisé doit être au préalable déclaré.
  • 70. 70 La déclaration d'une fonction a por but d'avertir le compilateur que cet objet va être utilisé et de lui préciser le type de son résultat et de chacun de ses paramètres formels éventuels. Une fonction est déclarée dans un fichier à partir : * soit de sa définition (en-tête + corps), * soit de la simple donnée de son prototype: <type> <identificateur de fonction> (liste des paramètres) ; Exemple: modifions le programme p_prin.c précédent. cours_C> cat prog_prin2.c double ce_reel(void) /* prototype de la fonction ce_reel() */ void main(void) { double le_reel; le_reel = ce_reel(); printf(" valeur de le_reel : %f .n", le_reel); }/* main de p_prin1.c*/
  • 71. 71 Exemple de déclaration et d'appel de fonction Cours_C> cat bissextile.c #include <stdio.h> int I_annee; int cette_annee_est bissextile(void) { if (!(I_annee % 4) && I_annee % 100 || !(I_annee % 400)) return 1; else return 0; } /* cette année est bissextile */ void main(void) { printf(" Donnez une année :"); scanf("%d", &I_annee); if (cette_annee_est_bissextile()) printf("l'année %d est bissextile.n", I_annee); else printf("l'année %d n'est pas bissextile.n", I_annee); }
  • 72. 72 cours_C> cat pgcd1.c #include <stdio.h> long int le_a , le_b; long int ce_pgcd(void) { while ( le_a != le_b) if (le_a > le_b) le_a - = le_b; else le_b - = le_a; return le_a; } /* ce_pgcd */ void main(void) { printf("Donnez deux nombres >0"); scanf("%ld %ld", &le_a, &le_b); printf(" le pgcd est %ld. n", ce_pgcd()); } /* main de pgcd1.c */
  • 73. 73 Les paramètres formels Une écriture plus élégante de la fonction ce_pgcd, consiste à utiliser les paramètres formels. cours_C> cat pgcd2.c #include <stdio.h> long int ce_pgcd(long int tel_a , tel_b;) { while ( tel_a != tel_b) if (tel_a > tel_b) tel_a - = tel_b; else tel_b - = tel_a; return tel_a; } /* ce_pgcd */ void main(void) { long int le_a , le_b; printf("Donnez deux nombres >0"); scanf("%ld %ld", &le_a, &le_b); printf("le pgcd de %ld et %ld est %ld.n",le_a,le_b, ce_pgcd(le_a,le_b)); } /* main de pgcd1.c */
  • 74. 74 Le mécanisme d'appel est le suivant: • dans le programme appelant les arguments éventuels sont évalués, •Pour chaque paramètre, une variable "interne" à la fonction appelée est crée et reçoit la valeur de l'argument; cette variable est détruite dès que la fonction appelée se termine. 180 135 le_a le_b main 180 tel_a tel_b 135 Ce_pgcd Ce_pgcd() travaille sur des copies et non sur les originaux Les variables le_a et le_b sont locales à la fonction main et ne sont donc pas accessibles de la fonction ce_pgcd.
  • 75. 75 La récursivité Une fonction est dite récursive si elle s'appelle elle-même. Par exemple, réécrivons la fonction ce_pgcd en appliquant strictement la définition : long int ce_pgcd( long int tel_a , long int tel_b) { if (tel_a == tel_b ) return tel_a ; else if ( tel_a > tel_b ) return ce_pgcd( tel_a -tel_b , tel_b ) else return ce_pgcd( tel_a , tel_b -tel_a ) } /* ce pgcd */ Une fonction récursive doit contenir une condition d'arrêt.
  • 76. 76 Les variables Déclaration et définition d'une variable. La déclaration précise les caractéristiques d'une variable; la définition lui réserve aussi de la place en mémoire: elle est alors créée. Cette réservation s'appelle l'allocation; elle peut intervenir soit à la compilation, soit à l'exécution. Toute variable doit être déclarée avant toute utilisation. Distinguons trois sortes de variable. a) Les variables de fichier: elles sont déclarées à l'extérieur de toute fonction. b) Les variables de bloc : elles sont déclarées à l'intérieur d'un bloc. c) Les paramètres d'une fonction
  • 77. 77 Initialisation. En C, initialiser une variable c'est lui affecter une valeur au moment de son allocation; l'affectation apparaît donc dans la définition. Syntaxe : [classe] <type> <identificateur> = <expression> Exemple int I_entier = 12 ; A chaque fois que la variable l_entier est créée, le nombre 12 lui est affecté
  • 78. 78 Visibilité d'une variable. Rappelons qu'une variable doit être déclarée avant son utilisation et que la portée d'une déclaration est le fichier. a) Une variable de fichier est visible (utilisable) de sa déclaration jusqu'à la fin du fichier. b) Un paramètre de fonction n'est visible que du bloc de fonction. c) Une variable de bloc n'est visible que de son bloc. Toutefois la déclaration d'un paramètre ou d'une variable de bloc annule localement la déclaration de toute variable de même nom faite à l'extérieur de ce bloc. Ainsi :
  • 79. 79 Les variables de fichier I_entier et le_reel ne sont visibles que des blocs D et C. Le paramètre I_entier de la fonction f n'est visible que des blocs A et B. La variable le_reel du bloc B n'est visible que de B. le_reel représente trois variables distinctes suivant que l'on se trouve dans A, dans B ou dans C ou D.
  • 80. 80 Redéclaration d'une variable. Droit d'accès. On peut redéclarer une variable de fichier, évidemment sous le même nom et avec le même type, en faisant précéder cette déclaration du mot clé extern. Exemple: extern int I_entier ; . La redéclaration n'a de sens que si la variable "originale" est accessible et est effectivement déclarée et allouée (c'est à dire définie) "ailleurs" afin que l'on puisse accéder à la donnée qu'elle contient. Durée de vie d'une variable. Une variable est : -soit créée (allouée) à la compilation : elle existe en mémoire tant que dure la tâche, -soit créée à l'exécution à chaque fois que cela est nécessaire et détruite à la fin de son utilisation.
  • 81. 81 Classe de mémorisation d'une variable. En C, il y a quatre classes de variables: externe, statique, automatique, registre. Syntaxe complète de la déclaration d'une variable. [classe] <type> <identificateur> [=<valeur>]; a)Externe. Une variable de classe "extern " est : -soit définie dans le fichier à l'extérieur de toute fonction (c'est donc une variable de fichier). Elle est accessible à partir de n'importe quel fichier du programme: elle est "exportable"; bien sûr, elle doit être déclarée dans les fichiers où elle n'est pas définie. On peut ne pas faire précéder sa définition du terme "extern". Cette variable est de classe extern au sens" global " .
  • 82. 82 -soit définie "ailleurs" .Il faut alors indiquer explicitement sa classe par le mot clé extern. C'est alors une simple déclaration; ce mécanisme permet d'"importer" une variable globale d'un fichier à un autre. La norne fournit un moyen très simple de distinguer ces "deux" points : -une variable de fichier de classe extern est définie si elle est initialisée et si le mot extern n'est pas précisé, -une variable de classe extern est simplement déclarée si on spécifie le mot extem sans préciser d'initialisation.
  • 83. 83 b) Statique. Une variable de classe "static" est allouée à la compilation dans la zone des données statiques; elle existe donc en mémoire tant que Dure la tâche. Elle n'est accessible Que du bloc ou fichier où elle est définie. c) Automatique. Une variable de classe "auto" est allouée à l'exécution dans la pile. Elle est créée lorsque le bloc dans lequel elle est définie devient actif; elle est détruite à la sortie du bloc. d) Registre. Une variable de classe "register" est allouée à l'exécution dans l'un des registres de la machine. Elle est créée lorsque le bloc dans lequel elle est déclarée devient actif; elle est détruite à la fin du bloc. On ne peut pas connaître l'adresse d'une variable "register". Si tous les registres sont occupés ou si sa taille ne lui permet pas d'être mémorisée dans l'un d'eux, une variable "register" est allouée automatiquement dans la pile.
  • 84. 84 Mettons en évidence la différence entre variable locale statique et automatique. void affiche( void ){ int le_nombre = 0; le_nombre ++ ; (void)printf("% d ", le_nombre ) ; } /* affiche () * / int main( void ){ int I_indice = 0 ; while ( ++I_indice < 10 ) affiche() ; (void)printf("n") ; return 0; } /* main de auto.c */ cours_C>cc auto.c cours_C>a.out 1 1 1 1 1 1 1 1 1 Dans la fonction affiche la variable le_nombre est de classe auto donc elle est créée et initialisée à chaque appel.
  • 85. 85 #include <stdio.h> void affiche( void ){ static int le_nombre = 0; ++ le_nombre ; (void)printf("% d ", le_nombre ) ; } /* affiche () * / int main( void){ int I_indice = 0 ; while ( ++I_indice < 10 ) affiche() ; (void)printf("n") ; return 0; } /* main de static.c * / cours_C>cc static.c cours_C>a.out 1 2 3 4 5 6 7 8 9 Ici la variable le_nombre est de classe "static" aussi elle a été créée et initialisée à la compilation, et existe tant que dure la tâche; elle conserve donc sa valeur entre chaque appel.
  • 86. 86 Les tableaux (1) • « Structure de données permettant de rassembler une suite de valeurs de même type en leur donnant un nom commun et en accédant aux valeurs de la suite par un indice »
  • 87. 87 Les tableaux (2) 0 2 3 4 5 6 1 int anArray [7] -> 9 3 12 1 1 2 0 anArray[3] v void main() { int anArray[7]; anArray[0]=9; anArray[1]=0; anArray[2]=3; ... } !
  • 88. 88 Les tableaux (3) 0 2 3 4 5 6 1 float anArray[7] -> anArray[3] v void main() { float anArray[7]={9.5,0.2,3.1,5.8,1,1.2,6}; anArray[0]=9.5; anArray[1]=0.2; anArray[2]=3.1; ... } 9.5 0.2 3.1 5.8 1 1.2 6
  • 89. 89 Les tableaux (4) • Parcours de la totalité d’un tableau : #define ARRAY_SIZE 1000 for (i=0;i<ARRAY_SIZE;i++) { … }
  • 90. 90 Les tableaux (5) • Recherche dans un tableau : #define ARRAY_SIZE 1000 void main() { int searchingArray[ARRAY_SIZE]; int element,i=0; initialization(searchingArray,&element,ARRAY_SIZE); while((i< ARRAY_SIZE) && (searchingArray[i]!=element)) i++; if (i== ARRAY_SIZE) printf("Element %d not found !n",element); else printf("Element %d found at indice %dn" ,element,i); }
  • 91. 91 Les tableaux (6) • Tableaux et fonctions • Passage de paramètres – void readMarks(float markArray[], int nbMark) • Utilisation dans la fonction: – markArray[3]=9.75 • Appel : – readMarks(SMIMarks,nbStudentSMI);
  • 92. 92 Les tableaux (7) • Résumé : – Parcours de tous les éléments du tableau -> boucle for – Parcours partiel d’un tableau en connaissant les bornes inférieures et supérieures -> boucle for – Parcours partiel d’un tableau lorsque la borne supérieure ou inférieure n’est pas connue -> boucle while ou do…while
  • 93. 93 Les chaînes de caractères • Chaîne de caractères -> tableau spécial o l l e h 0 o l l e h Chaîne de caractères Tableau de caractères Fin de chaîne • Attention prévoir un caractère de plus pour le 0 !!!
  • 94. 94 Les chaînes de caractères (2) • Ordinateur ne comprend que le binaire • Représentation des caractères par un nombre entier : c ’est l ’ASCII • ASCII : American Standard Code for Information Interchange • Tableau de correspondance entre lettre et représentation ASCII -> table ASCII
  • 95. 95 Les chaînes de caractères (3) l’ASCII • Proposé par l ’ANSI (AN Standards Institute) en 1963, finalisé en 68, utilisé à partir de 80 • Créé par Bob Bemer d’IBM • Codage sur 7 bits avec en plus l’escape caracter • 32 premiers caractères sont des caractères de contrôle (7 est une sonnerie, 8 effacement du caractère précédent, 13 retour à la ligne, …)
  • 96. 96 Les chaînes de caractères (3) l’ASCII • Exemple de codage ASCII : Notation ASCII décimale Notation humaine 104 101 108 108 111 0 h e l l o 0 68 65 6C 6C 6F 0 Notation ASCII hexadécimale
  • 97. 97 Les chaînes de caractères (4) l’ASCII • C ’est l ’ordinateur qui gère la conversion • Utiliser de préférence la notation humaine (c ’est plus clair pour les humains…) • ‘A’ est équivalent à 65, ‘a’ à 97, etc. • Ex : – char mLetter=‘a’+12;
  • 98. 98 Les chaînes de caractères (2) 0 2 3 4 5 1 char aString [6] -> aString[3] v #include <string.h> void main() { char aString[6]="hello0"; aString[0]=‘h’; aString[1]=‘e’; ... strcpy(aString,"hello"); } 0 o l l e h
  • 99. 99 Les chaînes de caractères (3) • Initialisation d’une chaîne : – Lors de la déclaration – Element par élément • Fonctions dédiées : – scanf (stdio.h) – strcpy (string.h)
  • 100. 100 Les chaînes de caractères (4) • Affichage avec printf : • printf(“%sn”,myString);
  • 101. 101 Les chaînes de caractères (5) Les fonctions standard • Longueur : length=strlen(myString); • Copie : strcpy(myString,”hello”); • Concaténation :strcat(myString,”lo”); • Comparaison :strcmp(string1,string2); • Transformation en entier : integer=atoi(myString); • Transformation en flottant : floatingPoint=atof(myString);
  • 102. 102 Les tableaux à plusieurs dimensions • 2 dimensions – Déclaration : int matrix[LINE_SIZE][COL_SIZE]; – Utilisation : matrix[4][3]=4; • 3 dimensions – Est-ce bien utile ?
  • 103. 103 Structures en C • Tableau : ensemble de valeurs de même type • Structure : ensemble de valeurs de types différents • Une structure s’utilise comme un type de données
  • 104. 104 Structures : Définition struct Student { char firstName[50]; char lastName[50]; int age; }; int main() { struct Student toto; toto.age=19; return 0; } Champ Définition de la structure Ne pas oublier le ; Déclaration d’une variable Accès aux champs avec .
  • 105. 105 Structures : Définition • Définition globale ou dans le header (.h) • mot-clef struct devant la déclaration de variable (possibilité d’utiliser un typedef) • . est l ’opérateur d ’accès aux champs
  • 106. 106 Structures : Imbrication struct Date { int jour,mois,annee; }; struct Etudiant { char nom[50]; char prenom[50]; int age; struct Date dateInscription; }; int main() { struct Etudiant toto; toto.dateInscription.jour=1; return 0; }
  • 107. 107 Tableaux de structures struct Etudiant { char nom[50]; char prenom[50]; int age; }; int main() { struct Etudiant smi[50]; smi[0].age=19; return 0; }
  • 109. 109 Plan du cours • La notion d'adresse mémoire • La notion de pointeur • Pointeurs et passage de paramètres • Pointeurs et tableaux • Pointeurs et chaînes de caractères • Allocation dynamique de mémoire • Les allocations mémoire en C
  • 110. 110 La notion d'adresse mémoire La définition de variable int i = 5; peut être interprétée de 2 façons. Point de vue conceptuel Point de vue du compilateur C • i est un nom symbolique qui désigne une variable qui prend des valeurs entières i 5 • i est une zone mémoire dimensionnée pour contenir des valeurs entières • le compilateur attribue une adresse à i en mémoire 5 102 adresse mémoire
  • 111. 111 Accès à l'adresse mémoire d'une variable • l'adresse d'une variable est une donnée en elle-même => on peut manipuler les adresses mémoire • le langage C autorise : -> l'accès à l'adresse mémoire d'une variable -> la manipulation des adresses mémoire à l'aide d'opérateurs -> la déclaration de variables dont les valeurs sont des adresses mémoire (notion de pointeur) • l'opérateur "&" si i est une variable entière, alors &i est une expression dénotant l'adresse de i 5 &i
  • 112. 112 La notion de pointeur • Déclaration d'une variable pointeur sur un type • Affectation à un pointeur • L'opérateur * pi *pi variable pointeur variable pointée l'opérateur * permet d'accéder à la variable pointée : il sert à déréférencer le pointeur 5 int i = 5; ==> pi = &i; int * pi; /* pi est un pointeur sur entier */ char * pc; /* pc est un pointeur sur caractère */ -> on peut déclarer un pointeur sur un type quelconque i ⇔* (&i)
  • 113. 113 Les opérations sur les pointeurs •le déférencement "*" • l'affectation "=" • les opérateurs de comparaison "==", "!=" • les opérateurs "+" et "-" sur les adresses • la constante NULL est une valeur spéciale du fichier stdio.h -> un pointeur à NULL ne pointe sur rien • les opérations d'allocation dynamique de la mémoire malloc et de désallocation free offertes par la librairie standard (fichier stdlib.h)
  • 114. 114 Un programme illustrant les pointeurs main () { int i = 5, j = 9; int *p1, *p2; /* deux pointeurs sur entier */ p1 = &i; /* *p1 est la variable i */ p2 = p1; /* p2 désigne la variable pointée par p1, c'est à dire i */ *p1 = 9; /* la variable i est modifiée */ if (p1 == p2) printf (" Nécessairement *p1 == *p2 "); p2 = &j; /* *p2 est la variable j */ if (*p1 == *p2) printf (" Ne signifie pas p1 == p2 !!! "); }
  • 115. 115 Pointeurs et typage • Typage d'un pointeur - un pointeur est typé par le type de l'objet pointé int * pi1, * pi2; /* pi1 et pi2 sont de type pointeur sur entier */ char * pc; /* pc est de type pointeur sur caractère */ • Affectation entre pointeurs - l'affectation p1 = p2 est correcte si p1 et p2 sont de même type - pi1 = pi2; /* affectation correcte */ - pi1 = pc; /* affectation erronée !!! */
  • 116. 116 Passage de paramètres par valeur #include <stdio.h> int carre ( ) { return (x * x); } main () { int i = 3; int car; car = carre ( ); printf ("%d", car); } main Carre i i car car i 3 copie valeur retour valeur avant appel de carre appel de carre fin de l'exéc. de carre 3 3 3 9 9 car x int x i
  • 117. 117 Passage de paramètres par adresse #include <stdio.h> void raz ( ) { *ip = 0; } main () { int i = 3; raz ( ); printf ("%d", i); } main Raz i i i 3 copie avant appel de raz appel de raz fin de l'exéc. de raz 3 int *ip &i &i ip adresse 0 *ip
  • 118. 118 Synthèse sur le passage de paramètres • Passage par valeur - la valeur du paramètre effectif est recopiée dans le paramètre for - le paramètre effectif est la valeur d'une expression - le paramètre effectif ne peut pas être modifié par la fonction • Passage par adresse - l'adresse du paramètre effectif est recopiée dans le paramètre form - le paramètre effectif est une variable - le paramètre effectif peut être modifié par la fonction - un tableau est toujours passé par adresse
  • 119. 119 Pointeurs et tableaux • Identificateur de tableau le nom d'un tableau est une constante dont la valeur est l'adresse du premier élément du tableau 0 1 2 ou &t[0] • Opérateurs "+" et "-" sur les pointeurs int *p; p = &t[1]; ==> p+1 pointe sur t[2] et p-1 pointe sur t[0] • Equivalence tableau / pointeur int t[N]; ==> &t[k] equivaut à t+k pour k dans 0..N-1 t int t[3];
  • 120. 120 Tableau en paramètre de fonction • Prototype d'une fonction triTableau void triTableau (int tab[], int n); • Appel de la fonction triTableau int t[3] = {4, 7, 2}; triTableau (t,3); • Passage du tableau t en paramètre à l'appel de triTableau, l'argument tab est initialisé avec &t[0] ==> un tableau est toujours passé par adresse /* tab est une variable de type pointeur sur entier */ /* t est une constante de type pointeur sur entier */
  • 121. 121 Pointeurs sur tableaux int t1[3] = {4, 6, 1}; int *p1 = t1; int t2[3] = {2, 7, 9}; int *p2 = t2; 4 6 1 2 7 9 p1 p2 0 1 2 p2 = p1; 4 6 1 2 7 9 p1 p2 0 1 2 4 1 2 7 9 p1 p2 0 1 2 - 5 *(p2+1) = - 5 ; ==> modification de t1[1] !!! t1 t2 t1 t2 t2 t1
  • 122. 122 Pointeurs et chaînes de caractères • Constantes chaînes de caractères - "ada", "pascal" sont des constantes littérales - une constante chaîne de caractères est implantée comme une séquence de caractères, terminée par le caractère '0' - sa valeur est l'adresse de son premier caractère - son type est pointeur sur caractère • Pointeurs sur chaîne de caractères char * ch = "ada"; • Tableaux de caractères char tc[] = {'a', 'd', 'a', '0'}; a a d 0 non modifiable !! ch a a d 0 modifiable !! tc non modifiable !! modifiable !!
  • 123. 123 Allocation dynamique de mémoire • Principe de l'allocation dynamique - le programmeur alloue demande au système d'exploitation de lu allouer de la mémoire durant l'exécution - les variables allouées dynamiquement sont stockées dans une zone mémoire dédiée appelée tas (heap) • Fonctions d'allocation - fournies par la bibliothèque standard : fichier <stdlib.h> - allocation d'une zone mémoire : fonction malloc - désallocation d'une zone mémoire : fonction free
  • 124. 124 La fonction malloc • L'opérateur sizeof - donne la taille en octets d'un type ou d'une expression - sizeof (int) vaut 4, sizeof (char) vaut 1, ... - int i; => sizeof i vaut 4 • Allocation d'une variable de type simple int * ip; ip = malloc ( sizeof (int) ); /* ou malloc ( sizeof *ip )*/ • Allocation d'une variable structurée typedef struct {float re,im;} Complexe; Complexe * cp; cp = malloc ( sizeof (Complexe) ); /* ou malloc ( sizeof *cp ) */
  • 125. 125 La fonction free • Contexte initial z *z z->re ou (*z).re z->im ou (*z).im 0.0 1.0 Complexe * z; z = malloc (sizeof(Complexe)); z->re = 0.0; z->im = 1.0; • Suppression d'une variable dynamique free (z); z • Attention danger !!! - après free(z), une référence à *z est une erreur ! - suppression d'une variable dynamique désignée par n pointeurs ! ?
  • 126. 126 Les allocations mémoire en C • Allocation statique - variable externe à une fonction (variable globale) - variable locale à une fonction mais déclarée static - allocation statique à la compilation - initialisation par défaut à 0 • Allocation automatique - variable interne à une fonction (variable locale) - allocation automatique à l'exécution dans la pile (stack) - initialisation indéfinie • Allocation dynamique avec malloc - variable dynamique - allocation dynamique à l'exécution dans le tas (heap) - initialisation indéfinie
  • 128. Le type fichier • On manipule les fichiers par l’intermédiaire de structures FILE décrites dans stdio.h FILE *monFichier; – Nom physique – Type d’accès(binaire ou formaté … distinction floue) – Adresse du buffer – Position dans le fichier – Indicateur d’erreur • Trois fichiers/flux standard, ouvert par défaut: stdin, stdout et stderr
  • 129. Ouverture/Fermeture d’un fichier • Faire le lien entre le nom physique (chaîne de caractère, chemin absolu ou relatif) et le nom logique (nom du pointeur) • Ouvrir dans le mode choisi (binaire, écriture, écraser, lecture,…) • Se positionner au début de fichier fich = fopen(nom_physique, mode); TESTER si le fichier a été ouvert (pas null). fopen(nom, ``r``); →0 si le fichier n’existe pas. fopen(nom, ``w``); →0 si le chemin d’accès est faux. fclose(fich);
  • 130. Mode d’ouverture • r ouverture d’un fichier texte en lecture • w crée un fichier texte en écriture, écrase le contenu précédent si le fichier existait. • a ajoute: ouvre ou crée un fichier texte et se positionne en écriture à la fin du fichier. • r+ ouvre un fichier en mode mise à jour (lecture et écriture) • w+ crée un fichier texte en mode mise à jour, écrase le contenu précédent si le fichier existait. • a+ ajoute, ouvre ou crée un fichier texte en mode mise à jour et se positionne en écriture à le fin du fichier.
  • 131. Exemple FILE *fich; char nom[100]; printf(``nom du fichier à lire : n``); scanf(``%s``,nom); if( (fich=fopen(nom, ``r``)) ==NULL) exit(1);
  • 132. Les entrées/sorties caractère • int getc(FILE *); int fgetc(FILE *); int getchar(); • int putc(FILE *); int fputc(FILE *); int putchar(); Exemple: void main(void){ int c; FILE *fich; fich = fopen(``données``, ``r``); do{ c = getc(fich); } while(c= = EOF); } Autre test sortie: int feof(FILE *) retourne pas zéro si EOF
  • 133. Les entrées/sorties formatées • Les fonctions fprintf() et fscanf() s’utilisent exactement de la même façon que printf et scanf, il suffit d’ajouter un paramètre pointeur de fichier: FILE *fichier; fichier = fopen(nomFichier, ``w``); int x=25; fprintf(fichier, ``%dn``,x); Qui pourra être lu par: fscanf(fichier,``%d``,&a);
  • 134. Les entrées/sorties binaires bufferisées • Sur fichiers ouverts en binaire fich = fopen(monFichier, ``rb``); • size_t fread(void *ptr, size_t size, unsigned int n, FILE *stream); • size_t fwrite(void *ptr, size_t size, unsigned int n, FILE *stream); • Principe: écrire directement la représentation machine des variables (c’est-à-dire de leur contenu mémoire) • Exemple: short x =1024; 00000100 00000000 fprintf(fich,``%d``,x) écrira les 4 caractères ‘1’, ‘0’, ‘2’ et ‘4’ dans le fichier texte fwrite(&x, sizeof(x), 1, fich) écrira les deux octets dans le fichier
  • 135. Les entrées/sorties binaires bufferisées(2) • Avantages: stockage réduit et lecture/écriture efficace. (une copie de la mémoire) • Inconvénients: non portable (taille des objets diff.), non lisibles par éditeurs de textes. (créer des programmes scanf/fwrite et fread/printf C pour les convertir)
  • 136. Fonction de parcours du fichier int fseek(FILE *flux, long int offset, int flag); Modifie la position du pointeur de fichier (lieu du prochain accès). Flag: – SEEK_SET début de fichier – SEEK_CUR relativement à la position courante – SEEK_END fin du fichier
  • 137. Traitement des erreurs de gestion de fichier Accès à des fichiers est source d’erreurs multiples: • Lors de l’ouverture (fichier inexistant, droits restrictifs, manque de place, erreur matérielle) • Rencontre d’une fin de fichier • Manque de place sur l’unité concernée • Destruction de la structure FILE • Mauvaise opération sur pointeur de fichier
  • 138. Détection des erreurs • Seule l’erreur matérielle est détecté par le système, toute les autres ne provoquent PAS l’arrêt du programme: il faut les traiter. • Un indicateur ferror peu efficace (oui/non) int ferror(FILE *); • Un indicateur errno peu fiable • Détection de la fin de fichier avec feof (il faut avoir lu la fin de fichier pour la reconnaître) • Consulter les valeurs de retour des fonctions
  • 139. Détection des erreurs • nb_ecrit = fwrite(…,nblocs,fich); Si nb_ecrit == nblocs OK, si inf: erreur • nb_lu = fread(…, nblocs,fich); Si nb_lu == nblocs et !feof, OK Si nb_lu est inf. à nblocs et !feof, pb materiel Si nb_lu == 0 et feof, fin de fichier normal Si nb_lu !=0 et eof, fin de fichier anormal
  • 140. Détection des erreurs • ncar = fprintf(fich, …); si negatif alors pb • nb_lu = fsanf (fich,…); Si nb_lu == nb_attendu et !feof, OK Si nb_lu est inf. à nb_attendu et !feof, pb materiel Si nb_lu == EOF et feof, fin de fichier normal Si nb_lu !=EOF et eof, fin de fichier anormal
  • 141. Détection des erreurs • c_ecrit = fputc(…,fich); c_ecrit != EOF, l’écriture s’est bien déroulé sinon, erreur d’écriture par manque de place ou erreur matériel. • ret = fgetc(fich); ret != EOF et !feof lecture normale ret == EOF et !feof pb matériel feof fin de fichier normale