Vous êtes sur la page 1sur 56

07/03/2017

Langage C

© ESP, 2012 1

Plan (1/2)

1. Généralités
Historique du Langage C
Compilation en C : existence d’un préprocesseur
2. Les éléments constitutifs d’un programme source
Les identificateurs | Les mots clés | Les séparateurs | les commentaires …
3. Les types de base
4. Les Entrées-Sorties standard
5. Les opérateurs et les expressions
6. Les instructions de contrôles
L’instruction if
L’instruction switch
Les boucles en C (do…while | while | for )
L’instruction break
L’instruction continue
7. Les Tableaux et Les Pointeurs

© ESP, 2012 2

©Bull 2012 1
07/03/2017

Plan (2/2)

10. Les chaînes de caractères


Créer, utiliser ou modifier une chaîne
Généralités concernant les fonctions de manipulation de chaînes
11. Les Fonctions
12. Le type STRUCTURE
Déclarations des structures
Initialisation des structures
La définition de synonymes avec typedef
13. Les bibliothèques standards
14. Les bibliothèques personnalisées (et la compilation séparée)
15. Le préprocesseur (macros, inclusions)
16. La compilation conditionnelle
17. Le mode d’exécution Console et en Ligne de commande (les paramètres
de la fonction main)

© ESP, 2012 3

1 Généralités

a- Historique du Langage C
b- Compilation en C : Existence d’un préprocesseur

© ESP, 2012 4

©Bull 2012 2
07/03/2017

a- Historique du Langage C

Le langage C a été créé en 1972 par Denis Ritchie avec un objectif


relativement limité : écrire un système d’exploitation (UNIX).

Mais ses qualités opérationnelles l’ont très vite fait adopter par une large
communauté de programmeurs.

Une première définition rigoureuse du langage a été réalisée en 1978 par


Kernighan et Ritchie avec la publication de l’ouvrage The C programming
language.

De nombreux compilateurs ont alors vu le jour, en se fondant sur cette


définition, quitte à l’assortir parfois de quelques extensions.

© ESP, 2012 5

a- Historique du Langage C

Ce succès international de ce langage a conduit à sa normalisation, d’abord


par :
l’ANSI (American National Standard Institute), puis par
l’ISO (International Standardization Organisation), puis en 1993 par
le CEN (Comité Européen de Normalisation) en enfin en 1994, par
l’AFNOR.

En fait, et fort heureusement toutes ses normes sont identiques, et l’usage


veut qu’on parle de « C ANSI » ou de « C norme ANSI ».

© ESP, 2012 6

©Bull 2012 3
07/03/2017

b- Compilation en C : Existence d’un préprocesseur

Programme source, module objet et programme exécutable


Tout programme écrit en langage évolué forme un texte qu’on nomme un
programme source (extension du fichier source « .c »). En langage C, ce
programme source peut être découpé en un ou plusieurs fichiers source.

Chaque fichier source est traduit en langage machine, indépendamment des


autres, par une opération dite de compilation, réalisée par un logiciel ou une
partie de logiciel nommée compilateur.

Le résultat de cette opération porte le nom de module objet (extension « .o » ou


« .obj »). Bien que formé d’instructions machine (langage binaire), un tel module
objet n’est pas exécutable tel quel car :

– Il peut lui manquer d’autres modules objets


– Il lui manque, de toute façon, les instructions exécutables des fonctions standard
appelées dans le fichier source (par exemple printf, scanf, strlen…)

© ESP, 2012 7

b- Compilation en C : Existence d’un préprocesseur

Programme source, module objet et programme exécutable

Le rôle de l’éditeur des liens est précisément de réunir les différents modules
objet et les fonctions de la bibliothèque standard afin de constituer un
programme exécutable.

© ESP, 2012 8

©Bull 2012 4
07/03/2017

b- Compilation en C : Existence d’un préprocesseur

Compilation en C
En C, la traduction d’un fichier source se déroule en deux étapes totalement
indépendantes :
– Un prétraitement,
– Une compilation à proprement dite.

Ces deux étapes sont, la plupart du temps, enchaînées automatiquement, de


sorte qu’on a l’impression d’avoir affaire à un seul traitement.

Généralement, on parle de préprocesseur pour désigner le programme réalisant


le prétraitement ; en revanche, les termes de compilateur ou de compilation
restent ambigus puisqu’ils désignent tantôt l’ensemble des deux étapes, tantôt la
seconde.

© ESP, 2012 9

b- Compilation en C : Existence d’un préprocesseur

Compilation en C
L’étape du prétraitement consiste à une modification du texte d’un fichier
source, basée essentiellement sur l’interprétation d’instructions très
particulières dites directives à destination du préprocesseur ;

Ces dernières sont reconnaissables par le fait qu’elles commencent par le


symbole #.

Les deux directives les plus importantes sont :


– La directive d’inclusion d’autres fichiers source #include

– La directive de définition de macros ou de symboles #define

© ESP, 2012 10

©Bull 2012 5
07/03/2017

b- Compilation en C : Existence d’un préprocesseur

Compilation en C
La première est surtout utilisée pour incorporer le contenu de fichiers prédéfinis
dits fichiers en-tête (extension « .h »), indispensables à la bonne utilisation des
fonctions de la bibliothèque standard, la plus connue étant :

#include <stdio.h>

La seconde est très utilisée dans les fichiers en-tête prédéfinis. Elle est
également souvent exploitée par le programmeur dans les définitions de
symboles tels que :

#define NB_COUPS_MAX 100


#define TAILLE 25

© ESP, 2012 11

2 Les éléments constitutifs d’un programme source

Les identificateurs | Les mots clés | Les séparateurs | les


commentaires …

© ESP, 2012 12

©Bull 2012 6
07/03/2017

Les identificateurs

Dans un programme, beaucoup d’éléments (variables, fonctions, types …) sont


désignés par un nom qu’on appelle identificateur.

Comme dans la plupart des langages, un tel identificateur est formé d’une suite
de caractères choisis parmi les lettres, les chiffres ou le caractère « souligné »
(_);le premier d’entre eux étant nécessairement différent d’un chiffre.

Voici quelques identificateurs corrects :

Lg_lig valeur_5 _total _89

D’autre part, les majuscules et les minuscules sont autorisés mais ne sont pas
équivalentes. Ainsi, en C, les identificateurs ligne et Ligne désignes deux objets
différents.

© ESP, 2012 13

Les mots clés

Certains mots sont réservés par le langage C à un usage bien défini. On les
nomme des mots clés.

Un mot clé ne peut pas être employé comme un identificateur. Voici la liste des
mots clés classés par ordre alphabétique :

auto default float register struct volatile


break do for return switch while
case double goto short typedef
char else if signed union
const enum int sizeof unsigned
continue extern long static void

© ESP, 2012 14

©Bull 2012 7
07/03/2017

Les séparateurs

Dans notre langue écrite, les mots sont séparés par un espace, un signe de
ponctuation ou une fin de ligne. Il en va presque de même pour le langage C
dont les règles vont donc paraître naturellement.

Ainsi, dans un programme, deux identificateurs successifs entre lesquels la


syntaxe n’impose aucun caractère ou groupe de caractères particulier dit
séparateur, doivent impérativement être séparés par ce que l’on nomme un
espace blanc (le plus usité étant l’espace) :

On nomme espace blanc une suite de un ou plusieurs caractères choisis parmi :


espace, tabulation horizontale, tabulation verticale, changement de ligne ou
changement de page.

En revanche, dès que la syntaxe impose un séparateur quelconque, il n’est pas


nécessaire de prévoir d’espaces blancs supplémentaires. Cependant, en
pratique, des espaces améliorent généralement la lisibilité du programme.

© ESP, 2012 15

Les séparateurs
Les caractères séparateurs comprennent tous les opérateurs (+, -, *, =, +=, ==, …)
ainsi que les caractères dits de ponctuation :
( ) [ ] { } , ; : …
Par exemple, vous devez impérativement écrire (avec au moins un espace blanc
entre int et x) :

int x,y;
Et non
intx,y;

En revanche, vous pourrez écrire indifféremment (le caractère virgule étant un


séparateur) :

int n,compte,total,y;
Ou plus lisiblement

int n, compte, total, y ;

© ESP, 2012 16

©Bull 2012 8
07/03/2017

Les commentaires

Comme tout langage évolué, le langage C autorise la présence de commentaires


dans les programmes source. Il s’agit de textes explicatifs destinés aux lecteurs
du programme et qui n’ont aucune incidence sur la compilation.

Ces commentaires sont formés de caractères quelconques placés entre les


symboles /* et */. Ils peuvent apparaître à tout endroit du programme où un
espace est autorisé, y compris dans les directives à destination du préprocesseur.

En général, cependant, on se limitera à des emplacements propices à une bonne


lisibilité du programme.

© ESP, 2012 17

Les commentaires

Voici quelques exemples de commentaires :

/* programme de calcul de la racines carreés */

/* commentaire fantaisiste &&$£^^ () » <>< !!!???? */

/* commentaire s’étendant
sur plusieurs lignes
de programmes source */

/* =========================================
* commentaire quelque peu esthétique *
* et mis en boîte, pouvant servir, *
* par exemple, d’en-tête de programme *
========================================= */

© ESP, 2012 18

©Bull 2012 9
07/03/2017

3 Les types de base

© ESP, 2012 19

Les types de base

La manipulation d’une information fait généralement intervenir la notion de


type, c’est-à-dire la manière dont elle a été codée en mémoire. La connaissance
de ce type est nécessaire pour la plupart des opérations qu’on souhaite lui faire
subir.

Traditionnellement, on distingue les types simples dans lesquels une information


est, à un instant donné, caractérisée par une seule valeur, et les types agrégés
dans lesquels une information est caractérisée par un ensemble de valeurs.

© ESP, 2012 20

©Bull 2012 10
07/03/2017

Les types de base

Les types entier


Pour les différents types entiers prévus par la norme, il sera présenté ici les
différentes façons de les nommer et quelques éléments permettant de choisir le
type entier le plus approprié à un objectif donné seront également présentés.
Enfin, nous terminerons avec les différentes façons d’écrire des constantes
entières dans un programme source.

Les six types entiers


– En théorie, la norme ANSI prévoit qu’il puisse exister six types entiers différents
caractérisés par deux paramètres :
 La taille de l’emplacement mémoire utilisé pour les représenter,
 Un attribut précisant si l’on représente des nombres signés, c’est-à-dire des entiers
relatifs, ou des nombres non signés, c’est-à-dire des entiers naturels.

© ESP, 2012 21

Les types de base

Les types entier


Les six types entiers
– Pour chacun des six types, il existe plusieurs façons de les nommer, compte tenu de ce
que :
 Le paramètre de taille s’exprime par un attribut facultatif : short ou long,
 Le paramètre de signe s’exprime, lui aussi, par un attribut facultatif : signed ou
unsigned,
 Le mot clé int, correspond à un entier de taille intermédiaire, peut être omis, dès lors
qu’un des qualificatifs précédents est présent.

– Le tableau qui suit récapitule les différentes manières de spécifier chacun de ces six types
(on parle de spécificateur de type), ainsi que la taille minimale et le domaine minimal que
leur impose la norme, quelle que soit l’implémentation concernée.

© ESP, 2012 22

©Bull 2012 11
07/03/2017

Les types de base

Les types entier (Tableau : Les six types entiers prévus par la norme)
Dénomination Spécificateurs de type Taille minimale Domaine minimal
usuelle possibles (en octets)
Entier court signé short 2 -32 767 à +32 767
short int
signed short
signed short int
Entier court non signé unsigned short 2 0 à 65 535
unsigned short int
Entier signé int 2 -32 767 à +32 767
signed int
Entier non signé unsigned int 2 0 à 65 535
unsigned
Entier long signé long 4 -2 147 483 647 à
long int +2 147 483 647
signed long
signed long int
Entier long non signé unsigned long 4 0 à 4 294 967 295
unsigned long int

© ESP, 2012 23

Les types de base

Les types entier


Critères de choix d’un type entier
Compte tenu du grand nombre de types entiers différents dont on dispose, voici quelques
indications permettant d’effectuer son choix.

– N’utiliser les entiers non signés que lorsque cela est nécessaire
 A taille égale, un type entier non signé permet de représenter des nombres deux fois
plus grands (environ) qu’un type signé. Dans ces conditions, certains programmeurs
sont tentés de recourir aux types non signés pour profiter de ce gain.
 En fait, il faut être prudent dans la mesure où dès qu’on est amené à effectuer des
calculs, il est généralement difficile d’affirmer qu’on ne sera pas conduit, à un moment
ou un autre, à un résultat négatif non représentable dans un type non signé;

– Efficacité
 En général, le type int correspond au type standard de la machine, de sorte que l’on
est quasiment assuré que c’est dans ce type que les opérations seront les plus rapides.
On pourra l’utiliser pour réaliser des programmes portables efficaces, pour peu qu’on
accepte les limitations correspondantes.

© ESP, 2012 24

©Bull 2012 12
07/03/2017

Les types de base

Les types entier


Critères de choix d’un type entier
– Occupation mémoire
 Le type short est naturellement celui qui occupera le moins de place, sauf si l’on peut
se contenter du type char, lequel, comme on le verra plus loin, peut jouer le rôle d’un
petit entier.
 Toutefois, l’existence de contraintes d’alignement d’une part, d’autre part le fait que ce
type peut être plus petit que la taille des entiers manipulés naturellement par la
machine, peuvent conduire à un résultat opposé à celui escompté.
 Par exemple, sur une machine ou le type short occupe 2 octets et ou le type int occupe
4 octets, on peut aboutir à la situation suivante :
- Les informations de deux octets sont alignées sur des adresses multiples de 4, ce qui peut
annuler le gain de place escompté;
- L’accès à deux octets peut impliquer l’accès à quatre octets avec sélection des deux octets utiles
d’où une perte de temps.
 En pratique, le type short pourra être utilisé pour des tableaux car la norme impose la
contiguïté de leurs éléments ; on sera donc assuré d’un gain de place au détriment
éventuel d’une perte de temps.

© ESP, 2012 25

Les types de base

Les types entier


Ecriture des constantes entières
– Lorsque vous devez introduire une constante entière dans un programme, le langage C
vous laisse le choix entre trois formes d’écriture présentées dans le tableau suivant :
 Tableau : les trois formes d’écriture présenté

Forme Définition Exemples Remarques


d’écriture
Décimale correspond à notre notation +533 conseillée dans les cas
usuelle d’un nombre entier, avec 48 usuels (arithmétique
ou sans signe -273 classique)
Octale nombre écrit en base 8, précédé 014 équivalent à 12 peu portable, conseillée
du chiffre 0 037 équivalent à 31 pour imposer un motif
binaire.
Hexadécimale nombre écrit en hexadécimal 0x1A (16+10) équivalent peu portable, conseillée
(base 16, les chiffres supérieurs à à 26 pour imposer un motif
9 étant représentés par les lettres 0x3F (3*16+15) binaire.
A à F majuscules ou minuscules), équivalent à 63
précédé des deux caractères 0x
(ou 0X)

© ESP, 2012 26

©Bull 2012 13
07/03/2017

Les types de base

Les types caractère


La langage C dispose non pas d’un seul, mais de deux types caractères, l’un signé, l’autre
non signé. Cette curiosité est essentiellement liée à la forte connotation numérique de ces
deux types. Ici, nous examinerons les différentes façons de nommer ces types, leurs
caractéristiques et la façon d’écrire des constante dans un programme.
Les deux types caractère
– Les types caractère correspondent au mot clé char. La norme ANSI prévoit en fait deux types
caractère différents obtenus en introduisant dans le spécificateur de type, de façon facultative, un
qualificatif de signe, à savoir signed ou unsigned.

– Cet attribut intervient essentiellement lorsqu’on utilise un type caractère pour représenter de petits
entiers. C’est la raison pour laquelle la norme définit, comme pour les types entiers, le domaine
(numérique) minimal des types caractères.

 Tableau : les deux types caractère du langage C

Dénomination Noms de type possibles Taille (en Domaine minimal


usuelle octets)
Caractère non signé unsigned char 1 0 à 255
char (suivant l’implémentation)
Caractère signé signed char 1 -127 à 127
char (suivant l’implémentation)
© ESP, 2012 27

Les types de base

Les types caractère


Caractéristiques des types caractère
Le tableau suivant récapitule les caractéristiques des types caractère ;
– Tableau : les caractéristiques des types caractère

Caractéristiques Détails
Code associé à un caractère • indépendant de l’attribut de signe
• dépend de l’implémentation
Caractères existants • au moins le jeu minimal d’exécution
• ne pas oublier que certains caractères ne sont pas
imprimables
Influence de l’attribut de • en pratique, aucune, dans les simples manipulations de
signe variables (type conseillé : char ou unsigned char)
• importante si l’on utilise ce type pour représenter de
petits entiers (type conseillé signed char)
Manipulation d’octets • possible par le biais de ce type, compte tenu de
l’équivalence entre octet et caractère (type conseillé
unsigned char)

© ESP, 2012 28

©Bull 2012 14
07/03/2017

Les types de base

Les types caractère


Ecriture des constantes caractère
– Il existe plusieurs façons d’écrire les constantes caractère dans un programme. Elles ne sont pas
totalement équivalentes.

Les caractères imprimables


– Les constantes caractère correspondant à des caractères imprimables peuvent se noter de façon
classique, en écrivant entre apostrophes (ou quotes) le caractère voulu, comme dans ces exemples :
– 'a' 'y' '$' '<'

Les caractères disposant d’une « séquence d’échappement »


– Certains caractères non imprimables possèdent une représentation conventionnelle dite séquence
d’échappement, utilisant le caractère « \ », nommé « anti-slash ».

– Dans cette catégorie, on trouve également quelques caractères qui, bien que disposant d’un
graphisme, jouent un rôle particulier de délimiteurs, ce qui les empêche d’être notés de manière
classique entre deux apostrophes.

© ESP, 2012 29

Les types de base

Les types caractère


Tableau : les caractères disposant d’une séquence

Séquence Code ASCII Abréviation usuelle Signification


d’échappement (hexadécimal)
\a 07 BEL Cloche ou bip (alert ou audible bell)
\b 08 BS Retour arrière (Backspace)
\f 0C FF Saut de page (form Fedd)
\n 0A LF Saut de ligne (Line Feed)
\r 0D CR Retour Chariot (Carriage Return)
\t 09 HT Tabulation Horizontale (Horizontal
Tabulation)
\v 0B VT Tabulation Verticale (Vertical Tabulation)
\\ 5C \
\' 2C '
\" 22 "
\? 3F ?

© ESP, 2012 30

©Bull 2012 15
07/03/2017

Les types de base

Les types flottant


Les types flottant (appelés parfois, un peu à tord, réels) servent à représenter de manière
approchée une partie des nombres réels. Ils s’inspirent de la notation scientifique des
calculettes, dans laquelle on exprime un nombre sous forme d’une mantisse et d’un
exposant correspondant à une puissance de 10, comme dans 0.433 E 15 (mantisse 0,433,
exposant 15)
Ecriture des constantes flottantes
Comme dans la plupart des langages, les constantes réelles peuvent s’écrire
indifféremment suivant l’une des deux notations :
– Décimale
La notation décimale doit comporter obligatoirement un point (correspondant à notre virgule). La partie
entière ou la partie décimale peuvent être omises (mais bien sûr par toutes les deux en même temps !).
En voici quelques exemples corrects :
12.43 -0.38 -.38 4. .27

– Exponentielle
La notation exponentielle utilise la lettre e (ou E) pour introduire un exposant entier (puissance de 10),
avec ou sans signe. La mantisse peut être n’importe quel nombre décimal ou entier (le point peut être
absent dès que l’on utilise un exposant). En voici quelques exemples corrects :
4.25E4 4.25e+4 54.27E-32 48.e13

© ESP, 2012 31

Les types de base

Déclarations des variables d’un type de base


Rôle de la déclaration
– Comme on s’y attend, la déclaration d’une variable d’un type de base permet de préciser
son nom et son type, par exemple :
unsigned int n ; /* n est de type unsigned int */

– On peut déclarer plusieurs variables dans une seule instruction ; par exemple :
unsigned int n, i ;
Est équivalente à :
unsigned int n ;
unsigned int i ;

Initialisation lors de la déclaration


– Une variable peut être initialisée lors de sa déclaration comme dans :
int n = 5 ;
Cela signifie que la valeur 5 sera placée dans l’emplacement correspondant à n, avant le
début de l’exécution de la fonction ou du bloc contenant cette déclaration

© ESP, 2012 32

©Bull 2012 16
07/03/2017

5 Les opérateurs et les expressions

© ESP, 2012 33

Les opérateurs et les expressions

Les particularités des opérateurs et des expressions en C


– Dans la plupart des langages, une expression se définit comme l’indication d’une suite de
calculs à effectuer et dont le résultat constitue la valeur ; par ailleurs, il existe des
instructions ( affectation, écriture, … ) pouvant faire intervenir des expressions. Certes,
cet aspect classique se retrouve en C. Par exemple, dans l’affectation :
y = a * x + b ;
 Apparaît l’expression a*x+b ; de même, dans l’affichage :

printf ( "valeur %d", n + 2*p ) ;


 Apparaît l’expression n + 2*p.

– La principale instruction du langage C est ce qu’on nomme l’instruction expression, c’est-


à-dire une expression terminée par un point virgule. Toute expression peut devenir une
instruction en la faisant suivre d’un point virgule : sa valeur, si elle existe, est simplement
inutilisée à ce moment là. Par exemple dans :
k = i = 5 ;

© ESP, 2012 34

©Bull 2012 17
07/03/2017

Les opérateurs et les expressions

Priorité et associativité
– Lorsque plusieurs opérateurs apparaissent dans une même expression, il est nécessaire
de savoir dans quel ordre ils sont mis en jeu. En C comme dans les autres langages, on
utilise les règles de priorité qui permettent de définir exactement l’ordre dans lequel
doivent être évalués les opérateurs. Par exemple :
a + b * c /* * est prioritaire sur + : on fera donc
le produit de b par c avant d’ajouter a */

– En outre, les parenthèses permettent d’outrepasser ces règles de priorité, en forçant le


calcul préalable de l’expression qu’elles contiennent. Notez que ces parenthèses peuvent
également être employées pour assurer une meilleure lisibilité d’une expression.

– Ces règles de priorité sont totalement naturelles dans le cas des opérateurs
arithmétiques ; elles rejoignent alors les règles de l’algèbre traditionnelle. Quant aux
priorités des autres opérateurs, elles ont été manifestement définies de manière à éviter
au maximum le recours aux parenthèses ; ces dernières pourront toutefois toujours être
utilisées pour éviter toute ambiguïté au lecteur du programme.

© ESP, 2012 35

Les opérateurs et les expressions

Opérateurs arithmétiques
– On nomme opérateurs arithmétiques, les opérateurs permettant d’effectuer les
opérations arithmétiques classiques. A priori, ils portent sur des opérandes de type
numérique, mais l’addition et la soustraction pourront posséder des opérandes de type
pointeur.
– Tableau : les opérateurs numériques dans un contexte numérique

Opérateur Résultat Contraintes Remarques


opérandes
Unaires Il n’existe pas d’opérateurs
+op valeur de op aucune d’élévation à la puissance. Il est
-op opposé de op aucune nécessaire de faire appel :
• soit à des produits successifs
Multiplicatifs
pour des puissances entières
op1 * op2 produit de op1 par op2 aucune
pas trop grandes (par ex., on
op1 / op2 quotient exact de op1 par op2 flottants
calculera x3 comme x*x*x),
op1 / op2 quotient entier de op1 par op2 : entiers
• soit à la fonction pow de la
11/3 vaut 3, -11/3 vaut -3 ou -4
bibliothèque standard.
op1 % op2 reste de la division de op1 par op2 : entiers
11%3 vaut 2
Additifs
op1 + op2 somme de op1 et op2 aucune
op1 – op2 différence de op1 et op2 aucune

© ESP, 2012 36

©Bull 2012 18
07/03/2017

Les opérateurs et les expressions

Les opérateurs relationnels


– Comme tout langage, C permet de comparer des expressions à l’aide d’opérateurs relationnels (ou
« de comparaison »), comme dans :
2*a>b+5
– Toutefois, en langage C, il n’existe pas de véritable type logique (on dit aussi booléen), c’est-à-dire ne
prenant que les valeurs vrai ou faux ; en fait, le résultat d’une comparaison est un entier valant :
 0 si le résultat de la comparaison est faux,
 1 si le résultat de la comparaison est vrai.
– Ainsi, le résultat d’une comparaison peut, assez curieusement, intervenir dans des calculs
arithmétiques comme :
3 * ( 2 * a > b + 5 ) /* vaut soit 0, soit 3 */
( n < p ) + ( p > q ) /* vaut 2 si n < p < q, 1 ou 0 sinon */

Tableau : les opérateurs relationnels dans un contexte numérique


Opérateur Signification Résultat
< inférieur
<= inférieur ou égal
> supérieur • la valeur entière 1 si la condition est vraie.
>= supérieur ou égal • la valeur entière 0 si la condition est fausse.
== égal
!= différent

© ESP, 2012 37

Les opérateurs et les expressions


Les opérateurs relationnels
– Les quatre premiers opérateurs (<, <=, >, >=) ont la même priorité. Les deux derniers (==, !=) ont
également la même priorité, mais celle-ci est inférieure à celle des précédentes.

Ainsi une expression telle que :


a < b == c < d
Est interprétée comme :
( a < b ) == ( c < d )

Ce qui en C, a effectivement une signification, car les expressions a < b et c < d sont, finalement, des
quantités entières.

Tous ces opérateurs sont, comme la plupart des opérateurs, associatifs de gauche à droite. Cela signifie
que, si les règles de priorité et d’emploi de parenthèses ne suffisent pas à décider de l’ordre
d’application des deux opérateurs, on fait d’abord intervenir celui de gauche (comme on le fait avec les
opérateurs de l’algèbre traditionnelle).

Ainsi une expression telle que :


a<b<c
Est évaluée comme :
(a<b)<c

© ESP, 2012 38

©Bull 2012 19
07/03/2017

Les opérateurs et les expressions


Les opérateurs logiques
– Dans la plupart des langages, les opérateurs logiques servent à combiner des expressions
logiques (dont la valeur est soit vrai, soit faux) par des opérateurs logiques usuels de type
et, ou et de négation. Ces possibilités se retrouvent en langage C, mais sous une forme
assez particulière.

– Tout d’abord, C ne dispose pas de type logique ; en particulier, les opérateurs de


comparaison fournissent une valeur entière, ce qui impose aux opérandes des
opérateurs logiques d’être de type entier.

– Dans ces conditions, plutôt que de restreindre leur valeur à 0 et 1, les concepteurs du
langage ont préféré donner une signification aux opérateurs logiques dans tous les cas,
en considérant simplement que seul 0 correspond à « faux », tandis que toute autre
valeur correspond à « vrai ».

© ESP, 2012 39

Les opérateurs et les expressions


Les opérateurs logiques
– Tableau : les opérateurs logiques du langage C

Opérateur Signification et résultat Contraintes Remarques


opérandes
! op Négation logique de op :
1 si op nul, 0 sinon
op1 && op2 Et logique de op1 et op2 : && n’évalue son
Scalaire
1 si op1 et op2 tous deux non nuls, 0 deuxième opérande
(numérique ou
sinon que si nécessaire.
pointeur)
op1 || op2 Ou logique de op1 et op2 : || n’évalue son
0 si op1 ou op2 tous deux nuls, 1 sinon deuxième opérande
que si nécessaire.

© ESP, 2012 40

©Bull 2012 20
07/03/2017

Les opérateurs et les expressions


Les opérateurs logiques
– Comme tout opérande nul (caractère de code 0, entier 0, flottant 0 ou pointeur nul) est
considéré comme faux et que tout autre valeur est considérée comme vrai, les résultat
de ces opérateurs peut être défini par la table suivante :

– Tableau : les opérateurs logiques du langage C

Opérande 1 Opérateur Opérande 2 Résultat (entier)


0 0 0
0 non nul 0
&&
non nul 0 0
non nul non nul 1
0 0 0
0 non nul 1
||
non nul 0 1
non nul non nul 1
0 1
!
non nul 0

© ESP, 2012 41

Les opérateurs et les expressions


Les opérateurs d’affectation et d’incrémentation
– Le langage C possède la particularité de traiter l’affectation comme un opérateur. Cela
signifie qu’une opération telle que :
i=5
est une expression qui :
 d’une part réalise une action : l’affectation de la valeur 5 à i,
 d’autre part possède une valeur : celle de i après l’affectation, c’est-à-dire 5.
– Manifestement, le premier opérande de cet opérateur devra être modifiable. Les
expressions :
5=n
n+5=3
– n’auraient aucun sens. La notion de lvalue (expression désignant un objet modifiable),
sert précisément à désigner des opérandes modifiables.

© ESP, 2012 42

©Bull 2012 21
07/03/2017

Les opérateurs et les expressions


Les opérateurs d’affectation et d’incrémentation
– La faible priorité de l’opérateur d’affectation (elle est inférieure à celle de tous les
opérateurs arithmétiques et de comparaison) fait qu’on peut l’utiliser de façon naturelle,
sans recourir à des parenthèses.
– Par exemple, dans :
c=b+3
– il y a d’abord l’évaluation de l’expression b + 3. La valeur ainsi obtenue est ensuite
affectée à c ; il n’est pas nécessaire d’écrire (mais ce serait correcte) :
c=(b+3)

– Contrairement à la plupart des autres, cet opérateur d’affectation possède une


associativité de droite à gauche. C’est ce qui permet à une expression telle que:
i=j=5

d’évaluer d’abord l’expression j = 5 avant d’en affecter la valeur (5) à la variable i. bien
entendu la valeur finale de cette expression est celle de i après affectation, c’est-à-dire 5.

© ESP, 2012 43

Les opérateurs et les expressions


Les opérateurs d’affectation et d’incrémentation
– Par ailleurs, il existe d’autres opérateurs d’affectation qui permettent de condenser des
écritures telles que :
 n = n + 3 /* se condensera en n += 3 */
 p = p * 5 /* se condensera en p *= 3 */

– Ces opérateurs se nommeront opérateurs d’affectation élargie, tandis que « = » se


nommera affectation simple. Bien entendu, ces opérateurs d’affectation élargie
nécessiteront eux aussi, une lvalue en premier opérande.

– D’une manière générale, C permet de condenser des affectations de la forme suivante,


dans laquelle la mention lvalue désigne obligatoirement la même lvalue :

lvalue = lvalue opérateur expression


en
lvalue opérateur= expression

© ESP, 2012 44

©Bull 2012 22
07/03/2017

Les opérateurs et les expressions


Les opérateurs d’affectation et d’incrémentation
– Tableau : Les opérateurs d’affectation élargie

Opérateurs Opérande de gauche Opérande de droite


+= -= lvalue de type numérique expression numérique
lvalue de type pointeur expression numérique entière
*= /= lvalue de type numérique expression numérique

%= lvalue de type entier expression entière

&= |= ~= lvalue de type entier expression entière

<<= >>= lvalue de type entier expression entière

– Enfin, des opérateurs unaires ( à un opérande ), ++ et --, dits opérateurs


d’incrémentation, permettent dans certains cas, de condenser encore plus l’écriture :
n = n + 1 /* déjà condensable en n += 1 peut se condenser en n++ */
n = n - 1 /* déjà condensable en n -= 1 peut se condenser en n-- */

© ESP, 2012 45

4 Les Entrées-Sorties standard : stdio.h

© ESP, 2012 46

©Bull 2012 23
07/03/2017

Les entrées-sorties standard

Qu’est ce qu’une bibliothèque d’entrées-sorties ?


Une bibliothèque est un ensemble de fonctionnalités ajoutées à un langage de
programmation. Chaque bibliothèque à un thème. Par exemple (en langage C) :
1. La bibliothèque math.h contient les fonctions mathématiques de calcul numérique et
constantes comme M_PI pour représenter le nombre π.
2. La bibliothèque time.h contient les types et fonctions permettant de gérer la durée
(date et heure), temps d’exécution d’un programme.
3. etc…
4. la bibliothèque stdio.h contient les types et fonctions permettant de gérer les
entrées-sorties (saisies au clavier, affichage de texte, mais aussi de fichiers…).
L’extension .h est réservée aux fichiers d’en-tête, ou fichier header, qui servent lorsqu’on
ne peut pas mettre l’ensemble du programme dans un même fichier. grâce aux fichiers
header, on va pouvoir utiliser, dans un code C, des fonctions qui sont écrites dans d’autres
fichiers, éventuellement par d’autres programmeurs, ce qui est le cas pour les
bibliothèques standard telles que stdio.h.
Pour utiliser les fonctionnalités de stdio.h, il faut mettre au début du programme :
#include <stdio.h>
Il en de même pour les autres bibliothèques.

© ESP, 2012 47

Les entrées-sorties standard

Affichage de données sous format texte


Afficher des caractères
– Pour afficher un caractère, on peut utiliser la fonction putchar :
putchar (‘A’) ; /* Affiche un ‘A’ */
putchar (65) ; /* Affiche aussi un ‘A’ */

– Il y a une manière simple d’afficher un message (ou plus généralement une chaîne de
caractères, voir plus loin) par la fonction puts :
puts ("coucou !") ;

– La fonction puts va automatiquement à la ligne après l’affichage. Pour afficher un


message sans aller à la ligne, on peut utiliser printf :
printf ("coucou !") ;

© ESP, 2012 48

©Bull 2012 24
07/03/2017

Les entrées-sorties standard

Affichage de données sous format texte


Afficher d’autres données
– Pour afficher des nombres, il faut spécifier un format, c’est-à-dire qu’il faut préciser
comment le résultat doit être afficher. Prenons l’exemple d’un caractère affiché sous
deux formes différentes :
char caract = ‘A’ ;
printf ( "%c", caract ) ; /* affiche en tant que caractère ‘A’ */
printf ( "%d", caract ) ; /* affiche en tant que nombre 65’ */

– La spécification du format, si elle est erronée, peut provoquer un résultat


incompréhensible. Parfois, plusieurs formats d’affichage sont possibles pour une même
donnée. Ils produisent un affichage sous des formes différentes.

1. Pour afficher des nombres entiers, le format est %d :


int nombre = 185 ;
printf ("%d", nombre);
2. Pour afficher un réel (float ou double), un format usuel %f :
float x = 2.0 / 3.0;
printf ("%f", x);

© ESP, 2012 49

Les entrées-sorties standard

Affichage de données sous format texte


Afficher d’autres données
3. Pour afficher un réel (float ou double), avec plus de précision ( plus de chiffres
après la virgule), le format est %lf :
float x = 3.0 / 2.0 ;
printf ("%lf", x);

4. Pour afficher un réel en spécifiant le nombre de chiffres après la virgule, le format


est %.?f :
float x = 2.0 / 3.0;
printf ("%.3f", x); /* affichage de 0.667 */

5. Pour afficher un caractère, le format usuel %c :


char caract = 68 ;
printf ("%c", caract); /* affichage de ‘D’ */

6. Pour afficher une chaîne de caractères, le format %s :


char *coucou = "coucou !";
printf ("%s", coucou);

© ESP, 2012 50

©Bull 2012 25
07/03/2017

Les entrées-sorties standard

Affichage de données sous format texte


Afficher d’autres données
– Avec la fonction printf, on peut aussi combiner l’affichage de messages avec l’affichage de
données numériques :

float x = 3.0 / 2.0 ;


int entier = (int) f ; /* Conversion explicite (cast) */
printf ("La partie entière de %f est %d\n", f, entier );
printf ("La partie fractionnaire de %f est %f\n", f, f - entier );

– Rappelons que le caractère spécial ‘\n’ provoque un retour à la ligne.

© ESP, 2012 51

Les entrées-sorties standard

Lecture au clavier
– Comme dans le cas de l’affichage, des fonctions telles que getchar (qui permet de lire
un caractère) ou autres permettent de lire des données texte.
– La fonction scanf permet de lire des données avec les formats suivants (liste non
exhaustive) :
 %d pour le type int ;
 %u pour le type unsigned int ;
 %f pour le type float ;
 %lf pour le type double ;
 %c pour le type char ;
 %s pour le type chaîne (étudié plus loin)
Attention !!!
1. Ne pas oublier le & devant chaque variable dans scanf, cela provoquera une erreur
mémoire (erreur de segmentation)/
2. Contrairement aux erreurs sur le format d’affichage, qui provoquent en général un
affichage incompréhensible, un mauvais format dans scanf peut provoquer une
erreur mémoire. Notamment, dans scanf, les formats %f et %lf sont incompatibles
et dépendent strictement du type de données (float ou double)

© ESP, 2012 52

©Bull 2012 26
07/03/2017

6 Les instructions de contrôles

a- L’instruction if
b- L’instruction switch
c- Les boucles en C (do…while | while | for )
d- L’instruction break
e- L’instruction continue

© ESP, 2012 53

a- L’instruction if
L’instruction if permet de programmer une structure dite de choix (ou sélection ou
alternative), permettant de choisir entre deux instructions, suivant la valeur d’une
expression numérique jouant le rôle de condition.
La seconde partie, introduite par le mot clé else, est facultative, de sorte que l’instruction
if présente deux formes.

Les deux formes de l’instruction if


if (expression) if (expression)
instruction_1 instruction_1
else
instruction_2
expression expression quelconque de type scalaire (numérique ou pointeur)
instruction_1 ou instruction exécutable quelconque, c’est-à-dire simple, structurée
instruction_2 ou bloc

Cette instruction évalue l’expression mentionnée à la suite de if. Si elle est non nulle, on
exécute instruction_1 ; si elle est nulle, on exécute instruction_2 si cette dernière est
présente. Puis, dans tous les cas, on passe à l’instruction suivant cette instruction if.

© ESP, 2012 54

©Bull 2012 27
07/03/2017

a- L’instruction if

Exemples d’utilisation
1. if ( a < b ) max = a ;
else max = b ;

2. if ( a < b ) {
max = a ;
printf ( "Le maximum en a") ;
}
else {
max = b ;
printf ( "Le maximum en b") ;
}
3. max = b ;
if ( a > b ) max = a ;
printf ("Maximum : %d", max ) ;

© ESP, 2012 55

b- L’instruction switch
La principale vocation de l’instruction switch est de permettre de programmer ce que l’on
nomme usuellement une structure de choix multiple (ou sélection multiple), c’est-à-dire un
choix entre plusieurs possibilités, chaque possibilité s’exprimant par une ou plusieurs
instructions.

l’instruction switch (forme usuelle)


switch (expression)
{
case constante_1 : [ suite d’instructions_1 ]
N.B : Les crochets ( [ et ] )
case constante_2 : [ suite d’instructions_2 ]
signifient que leur contenu est

facultatif.
case constante_n : [ suite d’instructions_n ]
[ default : suite_d’instructions ]
}
expression expression de type entier (char,
short, int ou long) signé ou non
constante_i expression constante entière
suite_d’instructions séquence d’instructions Attention il ne s’agit pas
quelconques nécessairement d’un bloc

© ESP, 2012 56

©Bull 2012 28
07/03/2017

b- L’instruction switch
Lors de l’exécution, l’expression est évaluée et il y a branchement à l’étiquette case xxx
correspondante si elle existe ; dans le cas contraire, il y a branchement à l’étiquette default
si elle existe, à la suite de l’instruction switch sinon.
Exemple d’utilisation
#include <stdio.h>
main ()
{
int n ;
printf ("Donnez un entier : ") ;
scanf ("%d", &n );
switch ( n )
{
case 0 : printf ("nul\n") ;
case 1 :
case 2 : printf ("petit\n") ; break ;
case 3 : printf ("moyen\n") ; break ;
case 4 :
case 5 : printf ("grand\n") ; break ;
default : printf ("hors norme\n") ;
break ; /* facultatif mais bonne précaution */
}
}

© ESP, 2012 57

b- L’instruction switch

Choix entre if et switch


On démontre qu’il suffit théoriquement de disposer de deux structures de base
(choix et répétition) pour traduire tout programme. Dans ces conditions, le
switch peut apparaître comme une structure redondante par rapport à if. Il n’en
reste pas moins que, dès qu’on a affaire à une énumération de cas, switch peut
s’avérer plus pratique que if et conduire à des programmes plus lisibles.

Cependant, l’instruction switch semble souffrir de limitations sévères, dans la


mesure où, pour l’utiliser, il faut :
– que les conditions de sélections puissent, au bout du compte, porter sur des
valeurs entières.
– que chaque partie de la sélection soit associée à un nombre pas trop grand de
valeurs pour qu’on puisse les énumérer facilement sous la forme case xxx.

© ESP, 2012 58

©Bull 2012 29
07/03/2017

C1- La boucle do … while

L’instruction do… while permet de réaliser des boucle de type faire… tantque,
mais la richesse de la notion d’expression en C peu amener à la dénaturer
quelque peu.

L’instruction do… while


do instruction
while (expression) ;
instruction instruction quelconque : simple,
structurée ou bloc
expression expression quelconque de type nommée parfois « expression de
scalaire (numérique ou pointeur) contrôle de la boucle » ou
condition de poursuite.

Notez bien la présence obligatoire du « ; » après le while (expression)

© ESP, 2012 59

C1- La boucle do … while

Cette instruction exécute l’instruction puis elle évalue l’expression de contrôle


suivant les règles habituelles ;
Si cette dernière est nulle, elle passe à l’instruction suivant do… while et
l’exécution de la boucle est terminée ;
Dans le cas contraire (expression non nulle), on reprend le processus d’exécution
de instruction et ainsi de suite.

L’exécution d’une telle boucle peut prendre fin :


– de manière naturelle : la valeur de l’expression de contrôle est devenue nulle.
– de manière prématurée : une instruction de rupture de séquence (break, goto
ou return) a été exécutée de l’intérieur vers l’extérieur du corps de la boucle.

© ESP, 2012 60

©Bull 2012 30
07/03/2017

C1- La boucle do … while

Exemple d’utilisation

Utilisation naturelle de do… while


main ()
{
int n ;
do
{
printf ("Donnez un nb > 0 : ") ;
scanf ("%d", &n ) ;
printf ("Vous avez fourni : %d\n ", n ) ;
}
while ( n <= 0 ) ;
printf ("réponse correcte\n" ) ;
}

© ESP, 2012 61

C2- La boucle while

L’instruction while permet de réaliser des boucles de type tant que, mais la
richesse de la notion d’expression en C peut la dénaturer quelque peu.

L’instruction while
while (expression)
instruction
instruction instruction quelconque : simple,
structurée ou bloc
expression expression quelconque de type nommée parfois « expression de
scalaire (numérique ou pointeur) contrôle de la boucle » ou
condition de poursuite.

Contrairement à ce qui se passe pour do… while, la syntaxe n’impose ici aucun
point virgule.

© ESP, 2012 62

©Bull 2012 31
07/03/2017

C2- La boucle while

Cette instruction évalue l’expression de contrôle suivant les règles habituelles ;


Si cette dernière est nulle, elle passe à l’instruction suivant while et l’exécution
de la boucle est terminée ;
Dans le cas contraire (expression non nulle), on exécute l’instruction gouvernée
par while et on reprend le processus d’évaluation de l’expression et ainsi de
suite.

On notera bien qu’une telle boucle peut prendre fin :


– de manière naturelle : la valeur de l’expression de contrôle est devenue nulle.
– de manière prématurée : une instruction de rupture de séquence (break, goto
ou return) a été exécutée de l’intérieur vers l’extérieur du corps de la boucle.

© ESP, 2012 63

C2- La boucle while

Exemple d’utilisation

Utilisation naturelle de while


main ()
{
int n, som ;
som = 0 ;
while (som < 100 )
{
printf ("Donnez un nombre : ") ;
scanf ("%d", &n ) ;
som += n ;
}
printf ("somme obtenu : %d\n", som ) ;
}

© ESP, 2012 64

©Bull 2012 32
07/03/2017

C2- La boucle for

la boucle for permet de réaliser des boucles avec compteur mais sa nature
même, jointe à la richesse de la notion d’expression en C peu la dénaturer très
profondément.

La principale vocation de l’instruction for est de permettre de programmer ce


que l’on appelle les boucles avec compteur dans lesquelles une variable
particulière dite variable de contrôle ou compteur sert à compter les tours de
boucle.

Cependant, par sa nature même, for est en réalité une boucle de type tant que
(analogue à while), dans laquelle on peut préciser, par le biais d’expressions
appropriées :
– les actions à réaliser avant l’entrée dans la boucle ;
– les actions à réaliser à la fin de chaque tour ;
– la condition de poursuite

© ESP, 2012 65

C2- La boucle for

L’instruction for
for ( [ expression_1 ] ; [ expression_2 ] ; [ expression_3 ] )
instruction
instruction instruction quelconque : simple,
structurée ou bloc
expression_1 et expressions de type quelconque pas nécessairement scalaire ici.
expression_3
expression_2 expression de type scalaire si cette expression est omise,
(numérique ou pointeur) tout se passe comme si elle
avait pour valeur 1 (vrai)

Les crochets ( [ et ] ) signifient ici que leur contenu est facultatif.

© ESP, 2012 66

©Bull 2012 33
07/03/2017

C2- La boucle for

Cette instruction réalise les étapes suivantes :


1. On évalue expression_1 si elle est présente.
2. On évalue expression_2 (si elle est absente, cela revient à lui attribuer la valeur
1) ; si sa valeur est nulle, l’exécution de la boucle for est terminée ; dans le cas
contraire, on exécute l’instruction et on évalue expression_3 si cette dernière
est présente.
3. On recommence le processus en 2.

On notera bien qu’une telle boucle peut prendre fin :


– de manière naturelle : la valeur de expression_2 est devenue nulle ;
– de manière prématurée : une instruction de rupture de séquence (break,
goto ou return) a été exécutée de l’intérieur vers l’extérieur du corps de la
boucle formé par instruction.

© ESP, 2012 67

C2- La boucle for

Lien entre for et while


l’instruction for est une instruction while qui s’ignore. D’ailleurs, comme le
précise formellement la norme ANSI, l’instruction :
for ( expression_1 ; expression_2 ; expression3 )
instruction

est équivalente, en l’absence de branchements dans instruction, à :

expression_1 ;
while ( expression_2 )
{
instruction
expression_3 ;
}

© ESP, 2012 68

©Bull 2012 34
07/03/2017

d- L’instruction break
Couramment utilisée avec l’instruction switch, l’instruction break permet
également de provoquer la fin prématurée d’une boucle.

L’instruction break
break ;

Cette instruction peut être utilisée dans deux contextes différents, avec des rôles
semblables.
– Dans une instruction switch, elle met fin à l’exécution de l’instruction ; elle est quasiment
indispensable pour faire du simple aiguillage induit par switch un véritable choix
multiple.
– Dans une instruction de boucle (for, while ou do… while), elle provoque la sortie
(prématurée) de la boucle.
L’usage de break est naturellement bien plus répandu dans la première situation
que dans la seconde
En cas d’imbrication d’instructions de boucles ou d’instructions switch, break ne
met fin qu’à l’instruction la plus interne le contenant. On notera que l’instruction
structurée if n’est pas concernée par break.

© ESP, 2012 69

d- L’instruction continue

Alors que break permet de mettre fin prématurément à une boucle, continue
permet de forcer le passage au tour suivant.

L’instruction continue
continue ;

Cette instruction ne s’utilise que dans une boucle et son exécution force
simplement le passage au tour suivant, en ignorant les instructions situées entre
continue et la fin de la boucle.
Elle ne concerne que la boucle de niveau le plus interne la contenant.

© ESP, 2012 70

©Bull 2012 35
07/03/2017

7 Les Tableaux et Les Pointeurs

© ESP, 2012 71

A- Les Tableaux

Les tableaux à une dimension


Un tableau est un ensemble d’éléments de même type désignés par un
identificateur unique : Chaque élément est repéré par un indice précisant sa
position au sein de l’ensemble

0 1 2 3 4 5
tab
Tab[0] Tab[1] Tab[2] Tab[3] Tab[4] Tab[5]

La déclaration
int mois [12] = { 31,28,30,31,30,31,30,31,30,31,30,31 }

définit un tableau de type int de taille 12. Les douze composantes sont
initialisées par les valeurs 31, 28, ... , 30, 31. On peut accéder à la première
composante du tableau par mois[0], à la deuxième par mois[1],..., à la dernière
par mois[11].

© ESP, 2012 72

©Bull 2012 36
07/03/2017

A- Les Tableaux

Initialisation et réservation automatique


L'Initialisation
– Lors de la déclaration d'un tableau, on peut initialiser ses composantes en indiquant la
liste des valeurs respectives entre accolades.
– Exemples :
int A[5] = { 10, 7, 9, 0, 6 } ;
float B[3] = { 13.50, 7.00, 12.4 } ;
– Il faut veiller à ce que le nombre de valeurs dans la liste corresponde à la dimension du
tableau. Si la liste ne contient pas assez de valeurs pour toutes les composantes, les
composantes restantes sont initialisées à 0.
La réservation automatique
– Si la dimension du tableau n'est pas indiquée explicitement lors de l'initialisation, alors
l'ordinateur réserve automatiquement le nombre d'octets nécessaires.
– Exemples :
int A[] = { 10, 20, 30, 40, 50 } ;
– Réservation de 5 * sizeof ( int ) octets ( dans notre cas : 20 )

© ESP, 2012 73

A- Les Tableaux

Initialisation et réservation automatique


Affectation avec des valeurs provenant de l'extérieur
main()
{
int A[5];
int i; /* Compteur */
for( i=0 ; i<5 ; i++ )
scanf( "%d", &A[i] );
return 0;
}
Comme scanf a besoin des adresses des différentes composantes du tableau, il
faut faire précéder le terme A[i] par l'opérateur adresse '&'.

La commande de lecture scanf doit être informée du type exact des données à
lire. (Ici: %d ou %i pour lire des valeurs du type int)

© ESP, 2012 74

©Bull 2012 37
07/03/2017

A- Les Tableaux

Les tableaux à deux dimensions


Colonnes
0 1 2 3 4 5

0 Tab[0][0] Tab[0][1] Tab[0][2] Tab[0][3] Tab[0][4] Tab[0][5]


Lignes

tab 1 Tab[1][0] Tab[1][1] Tab[1][2] Tab[1][3] Tab[1][4] Tab[1][5]

2 Tab[2][0] Tab[2][1] Tab[2][2] Tab[2][3] Tab[2][4] Tab[2][5]

3 Tab[3][0] Tab[3][1] Tab[3][2] Tab[3][3] Tab[3][4] Tab[3][5]

Un tableau tab à 2 dimensions sur 4 Lignes et 6 Colonnes. Les éléments du tableau sont
accessibles en faisant tab [ i ][ j ] où i représente l’indice de la ligne et j l’indice de la
colonne de la cellule concernée.
Déclaration : int tab [ 4 ][ 6 ] ;
Accès en lecture
printf ("%d",tab[0][2]); {L’information contenue en ligne 1 colonne 3 est affichée à l’écran}
Accès en écriture
tab][3] = 36;
scanf ( "%d", &tab[1][3] ) ; { La valeur fournie est enregistrée en ligne 2 colonne 4}

© ESP, 2012 75

A- Les Pointeurs

Lorsque l’on déclare une variable, par exemple un entier i, l’ordinateur réserve
un espace mémoire pour y stocker les valeurs de i.
L’emplacement de cet espace dans la mémoire est nommé adresse
Un pointeur est tout simplement une variable spéciale qui permet de stocker
l’adresse d’une autre variable.
Par exemple si nous déclarons une variable entière i (initialisée à 10) et que l’on
déclare un pointeur p dans lequel on range l’adresse de i (on dit que p pointe sur
i ), on a par exemple le schéma suivant :

© ESP, 2012 76

©Bull 2012 38
07/03/2017

A- Les Pointeurs

Si un pointeur P contient l'adresse d'une variable A, on dit que 'P pointe sur A'.
Les pointeurs et les noms de variables ont le même rôle: Ils donnent accès à un
emplacement dans la mémoire interne de l'ordinateur. Il faut quand même bien
faire la différence:
– Un pointeur est une variable qui peut 'pointer' sur différentes adresses.
– Le nom d'une variable reste toujours lié à la même adresse.

Les opérateurs principaux


– La manipulation des pointeurs en C requiert :
 L’opérateur & dit « adresse de » : pour obtenir l’adresse d’une variable
 L’opérateur * dit « contenu de » : pour obtenir le contenu d’une adresse

– &<NomVariable> fournit l'adresse de la variable <NomVariable>


– *<NomPointeur> désigne le contenu de l'adresse référencée par le pointeur
<NomPointeur>

© ESP, 2012 77

A- Les Pointeurs

Déclaration d'un pointeur


<Type> *<NomPointeur> ;
déclare un pointeur <NomPointeur> qui peut recevoir des adresses de variables du
type <Type>

int *PtrNum ;
peut être interprétée comme suit:
– "*PtrNum est du type int" ou
– "PtrNum est un pointeur sur int" ou
– "PtrNum peut contenir l'adresse d'une variable du type int

© ESP, 2012 78

©Bull 2012 39
07/03/2017

A- Les Pointeurs

Remarque
Lors de la déclaration d'un pointeur en C, ce pointeur est lié explicitement à un
type de données. Ainsi, la variable PtrNum déclarée comme pointeur sur int ne
peut pas recevoir l'adresse d'une variable d'un autre type que int.

Exemple :

main () {
int n, m ;
int *p ; /* déclaration d’une variable de type
pointeur sur un entier */
n = 20 ; m = 10 ;
p = &n ; /*p pointe sur n ou p reçoit l’adresse de n */
*p = m ;
return 0 ;
}

© ESP, 2012 79

A- Les Pointeurs

Pointeurs et Tableaux
Le nom d'un tableau est un pointeur constant sur le premier élément du tableau.
En d'autre termes:
&tableau[0] et tableau sont une seule et même adresse.
En déclarant un tableau A de type int et un pointeur P sur int,
int A[10];
int *P;
L'instruction :
P = A ;
est équivalente à :
P = &A[0] ;
Si P pointe sur une composante quelconque d'un tableau, alors P+1 pointe sur la
composante suivante. Plus généralement,
 P + i pointe sur la i-ième composante derrière P et
 P - i pointe sur la i-ième composante devant P.

© ESP, 2012 80

©Bull 2012 40
07/03/2017

A- Les Pointeurs

Pointeurs et Tableaux
Le nom d'un tableau est un pointeur constant sur le premier élément du tableau.
En d'autre termes:
&tableau[0] et tableau sont une seule et même adresse.
En déclarant un tableau A de type int et un pointeur P sur int,
int A[10];
int *P;
L'instruction :
P = A ;
est équivalente à :
P = &A[0] ;
Si P pointe sur une composante quelconque d'un tableau, alors P+1 pointe sur la
composante suivante. Plus généralement,
 P + i pointe sur la i-ième composante derrière P et
 P - i pointe sur la i-ième composante devant P.

© ESP, 2012 81

8 Les chaînes de caractères

a- Créer, utiliser ou modifier une chaîne


b- Généralités concernant les fonctions de manipulation de chaînes

© ESP, 2012 82

©Bull 2012 41
07/03/2017

a- Créer, utiliser ou modifier une chaîne

Introduction
Il n'existe pas de type spécial chaîne ou string en C. Une chaîne de caractères est
traitée comme un tableau à une dimension de caractères. Il existe quand même
des notations particulières et une bonne quantité de fonctions spéciales pour le
traitement de tableaux de caractères.

Déclaration de chaînes de caractères en C

char <NomVariable> [<Longueur>];

Exemples
char NOM [20];
char PRENOM [20];
char PHRASE [300];

© ESP, 2012 83

a- Créer, utiliser ou modifier une chaîne

Espace à réserver
Lors de la déclaration, nous devons indiquer l'espace à réserver en mémoire
pour le stockage de la chaîne. La représentation interne d'une chaîne de
caractères est terminée par le symbole '\0' . Ainsi, pour un texte de n caractères,
nous devons prévoir n+1 octets.

Malheureusement, le compilateur C ne contrôle pas si nous avons réservé un


octet pour le symbole de fin de chaîne; l'erreur se fera seulement remarquer lors
de l'exécution du programme ...

Mémorisation d’un tableau de caractères


char TXT[10] = "BONJOUR !";

© ESP, 2012 84

©Bull 2012 42
07/03/2017

a- Créer, utiliser ou modifier une chaîne

Observation
Pour la mémorisation de la chaîne de caractères "BONJOUR !", C a
besoin de dix(!!) octets.
'a' est un caractère constant, qui a une valeur numérique :
Exemple : 'a' a la valeur 97 dans le code ASCII.
"a" est un tableau de caractères qui contient deux caractères :
– la lettre 'a' et le caractère NUL : '\0'
'x' est codé dans un octet
"x" est codé dans deux octets

© ESP, 2012 85

b- Les fonctions de manipulation de chaînes

Manipulation des chaînes de caractères


Les bibliothèques de fonctions de C contiennent une série de fonctions spéciales
pour le traitement de chaînes de caractères.

La bibliothèque « string.h »
Certaines fonctions seront étudiées en TP.

© ESP, 2012 86

©Bull 2012 43
07/03/2017

9 Les Fonctions

© ESP, 2012 87

Les fonctions

Le langage C permet de découper un programme en plusieurs parties nommées


souvent « fonctions ».

Cela se justifie par le fait que : Un programme écrit d’un seul tenant devient
difficile à comprendre dès qu’il atteint plus de deux pages de texte.

Une écriture modulaire permet de le scinder en plusieurs parties. Chacune de


ces parties peut également être décomposée, si nécessaire, en module plus
élémentaires. L’on évite les séquences d’instructions répétitives.

Elle permet le partage d’outils communs qu’il suffit d’avoir écrits et mis au point
une seule fois.

© ESP, 2012 88

©Bull 2012 44
07/03/2017

Les fonctions

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

typeRés NomFonct (typeParam1 Param1, typeParam2 Param2, … )


{
<Déclarations locales>
<instructions>
}

Par exemple

int plusUn (int a)


{
return a+1 ;
}

© ESP, 2012 89

Les fonctions

Déclaration et définition de fonction


En général, le nom d'une fonction apparaît à trois endroits dans un
programme :
– lors de la définition
– lors de la déclaration
– lors de l'appel

Définition
Dans la définition d'une fonction, nous indiquons :
– le nom de la fonction
– le type, le nombre et les noms des paramètres de la fonction
– le type du résultat fourni par la fonction
– les données locales à la fonction
– les instructions à exécuter

© ESP, 2012 90

©Bull 2012 45
07/03/2017

10 Le type STRUCTURE

a- Déclarations des structures


b- Initialisation des structures
c- La définition de synonymes avec typedef

© ESP, 2012 91

a- Déclarations des structures

Une structure est un type qui permet de stocker plusieurs données, de même
type ou de types différents, dans une même variable de type structure.
Une structure est constitué de plusieurs champs, chaque champ correspondant à
une donnée.
Exemple : Voici la déclaration d’une structure point qui contient trois champs x,
y, z de type float.

struct point
{ /* déclaration de la structure */
float x, y ; /* trois champs x, y , z */
float z ; /* les champs se déclarent comme des variables */
/* mais on ne peut pas initialiser les valeurs */
}
La déclaration d’une variable de type struct point se fait ensuite comme pour
une autre variable

struct point P ;

© ESP, 2012 92

©Bull 2012 46
07/03/2017

b- Initialisation des structures

Une fois la variable déclarée, on accède aux données x, y et z du point P par un


point. Ces données sont désignées dans le programme par P.x, P.y et P.z.

Ces données P.x, P.y et P.z de type float sont traitées comme n’importe quelle
autre donnée de type float dans le programme.

Notons que l’on pourrait rajouter d’autres données de types que l’on souhaite à
la suite des données x, y et z dans la structure.

© ESP, 2012 93

c- La définition de synonymes avec typedef

Pour éviter la répétition du mot struct, lors de la déclaration des variables de


type struct point, on peut définir un raccourci par un typedef lors de la définition
de la structure pour donner un nouveau nom à ce type :

/* définition d’un type POint3D */


typedef struct point
{
float x, y, z ; /* déclaration d’un nouveau type */
/* par typedef */
} Point3D ;

La déclaration d’une variable de type struct point se fait ensuite comme pour
une autre variable

Point3D P ;

© ESP, 2012 94

©Bull 2012 47
07/03/2017

13 Les bibliothèques standards

© ESP, 2012 95

13 Les bibliothèques standards

La norme ANSI fournit à la fois la description du langage C et le contenu d’une


bibliothèque standard, subdivisée en plusieurs parties (sous-bibliothèques)

A chaque sous-bibliothèque est associé


– un fichier en-tête comportant essentiellement :
 Les prototypes des fonctions correspondantes (contenues dans la bibliothèque)
 La définition de certains symboles utiles au bon fonctionnement des fonctions ou des
macros de la bibliothèque; Il s’agit soit de types ou synonymes définis par typedef,
soit de constante définies par #define.
– un fichier binaire (.lib) contenant le version précompilée des fonctions de la bibliothèque.

Nom de la bibliothèque stdio


Nom des fichiers stdio.h stdio.lib
/* Entêtes des fonctions de Codes en Binaire.
la bibliothèque Version précompilée du
Contenu des fichiers
*/ code source des fonctions
de la bibliothèque.

© ESP, 2012 96

©Bull 2012 48
07/03/2017

13 Les bibliothèques standards

Voici classée par ordre alphabétique, la liste de tous les fichiers en-tête prévus
par la norme.

Nom fichier en-tête Contenu


<assert.h> Macros de mise au point
<ctype.h> Test de catégories de caractères et conversions majuscules/minuscules
<errno.h> Gestion des erreurs
<float.h> Caractéristiques des types flottants
<limits.h> Caractéristiques des types entiers (et caractère)
<locale.h> Caractéristiques locales
<math.h> Fonctions mathématiques
<setjmp.h> Branchements non locaux
<signal.h> Traitement des signaux
<stdarg.h> Gestion des arguments variables
<stddef.h> Définitions communes
<stdio.h> Entrées-sorties
<stdlib.h> Utilitaires: conversion de chaines, nombres aléatoires, gestion de la mémoire,
communication avec l’environnement, arithmétique entière, caractères étendus,
chaînes de caractères étendus
<string.h> Manipulation de chaînes et de suite d’octets
<time.h> Gestion de l’heure et de la date

© ESP, 2012 97

14 Les bibliothèques personnalisées (et la


compilation séparée)

© ESP, 2012 98

©Bull 2012 49
07/03/2017

14 Les bibliothèques personnalisées


L’unique différence entre les bibliothèques personnalisée et les bibliothèques
standards réside dans le fait que les fonctions, macros et autres symboles de la
première sont créés, définis par le programmeur.

Nom de la bibliothèque MaBiblioPerso


Nom des fichiers MaBiblioPerso.h MaBiblioPerso.c
/* Entêtes des fonctions de Codes sources des
la bibliothèque, macros, fonctions compilés de
Contenu des fichiers définitions de symboles etc façon séparée.

*/

il s’agit de ses propres fonctions et symboles.


Les bibliothèques personnalisées ont pour avantage de permette un export d’un
projet à un autre de tout le contenu de la bibliothèque sans avoir à le recréer.
Elles facilitent la création de nouveau projet en langage C et réduisent le temps
d’implémentation.

© ESP, 2012 99

13 Les bibliothèques personnalisées

La compilation séparée
– Le langage C offre la possibilité d’éditer le code source en plusieurs fichiers (fichiers
sources C). Cela pour une meilleure organisation du travail et en vue de garantir
également une bonne maintenabilité du code.
– De ce fait, chaque fichier du projet est compilée séparément.

main.c mesfonctions.c mesfonctions_2.c


compilation séparée
main.o mesfonctions.o mesfonctions_2.o

– La compilation séparée génère pour chaque fichier un module objet correspondant.

Mise en place d’une bibliothèque personnalisée


– Vue en TP (Consultez le fichier de LAB)

© ESP, 2012 100

©Bull 2012 50
07/03/2017

15 Le préprocesseur (macros, inclusions, définitions)

© ESP, 2012 101

15 Le préprocesseur (macros, inclusions, définitions)

Le travail du préprocesseur consiste en un traitement du texte du fichier source


fondé sur l’interprétation d’instructions particulières, structurées en ligne et
qu’on nomme des directives.
– Pour le préprocesseur une directive se définit comme étant une ligne qui commence par
le symbole #.

– La directive #define offre deux possibilités à savoir la définition de symboles d’une part,
la définition de macros d’autres part.

– Dans le cas de la définition de symboles, le rôle du préprocesseur se limite à une simple


substitution d’un symbole par un texte quelconque. L’usage veut que ce texte
corresponde à une constante caractère, numérique ou chaîne.

– Dans le cas de la définition d’une macros, intervient, un peu comme dans une fonction
la notion de paramètres.

– Certes, le préprocesseur réalise ici encore une substitution mais celle-ci n’est pas
systématique puisqu’elle dépend des valeurs effectives des différents paramètres.

© ESP, 2012 102

©Bull 2012 51
07/03/2017

15 Le préprocesseur (macros, inclusions, définitions)

Définitions de simples symboles


– Une directive telle que :
– #define NBMAX 5
– demande de remplacer le symbole NBMAX par le texte 5, et cela chaque fois que ce
symbole apparaîtra dans la suite du fichier source.

– les instructions suivantes par exemple :

– int n = NBMAX :
– float tab [NBMAX]=[2*NBMAX];

– seront remplacés par:

– int n = 5:
– float tab [5][10];

© ESP, 2012 103

15 Le préprocesseur (macros, inclusions, définitions)

Définitions de macros
– Une directive suivante:
– #define carre(a) a*a

– ressemble aux différentes, avec une différence que le symbole à substituer se présente
sous la forme d’un identificateur suivi d’un paramètre entre parenthèses ; elle demande
au préprocesseur de remplacer dans la suite du fichier source tous les texte de la forme :
– carre(a) dans lequel a représente en fait un texte quelconque par :
– a*a

– Par exemple :
– carre(z) deviendra z*z
– carre(valeur) deviendra valeur*valeur

– Il est possible de définir une macro avec plusieurs paramètres :


– #define dif(a,b) a-b
– Dans ce cas dif(z,x) deviendra z-x

© ESP, 2012 104

©Bull 2012 52
07/03/2017

15 Le préprocesseur (macros, inclusions, définitions)

Définitions de macros
– La directive #define pour la définition de macros

#define^identificateur(liste_de_paramètres) liste_de_remplacement
identificateur Formé suivant les règles
habituelles concernant les
identificateurs
^ Représente un ou plusieurs On peut y trouver des espaces
espaces blancs autres que fin de blancs
ligne et/ou commentaire
liste_de_paramètres Liste de zéro, un ou plusieurs
identificateurs, obligatoirement
différents les uns des autres
séparés par des virgules
Liste_de_remplacement Texte quelconque qui sera
substitué, dans la suite du
fichier source, à un appel de
macro de la forme
identificateur(…)

© ESP, 2012 105

16 La compilation conditionnelle

© ESP, 2012 106

©Bull 2012 53
07/03/2017

16 La compilation conditionnelle

Un certain nombre de directives permettent d’incorporer ou d’exclure des


portions du fichier source dans le texte qui sera analysé par le préprocesseur.
Ces directives se classent en deux catégories selon la condition qui régit
l’incorporation.

la directive #ifdef

#ifdef^identificateur[^] #ifdef^identificateur[^]
Lignes_1 Lignes_1
#else[^] #endif[^]
Lignes_2
#endif[^]
^ Représente un ou plusieurs espaces
blancs(autres que la fin de ligne)
et/ou un ou plusieurs commentaires
Lignes_1 et Lignes_2 0, 1 ou plusieurs lignes de contenu
quelconque

© ESP, 2012 107

16 La compilation conditionnelle

la directive #undef
– Elle permet de supprimer la définition d’un symbole

la directive #ifndef
– Elle joue le même rôle que #ifdef, en inversant simplement les instructions incorporées
ou ignorées.

#ifndef^identifateur[^] #ifndef^identifateur[^]
Lignes_1 Lignes_1
#else[^] #endif[^]
Lignes_2
#endif[^]
^ Représente un ou plusieurs espaces
blancs(autres que la fin de ligne)
et/ou un ou plusieurs commentaires
Lignes_1 et Lignes_2 0, 1 ou plusieurs lignes de contenu
quelconque

© ESP, 2012 108

©Bull 2012 54
07/03/2017

16 La compilation conditionnelle
Exemple d’utilisation des macros et d’une compilation conditionnelle
fichier main.c initial fichier main.c destiné à la compilation à
proprement dite
#define NMAX 6 int main ()
#define TOTO {
#define afficher printf int x, y, z, i ;
#define calcul(a,b,c) a*b+c x = 6– 1;
#define debut { y = 2*6;
#define fin } z = 6;
for (i=0;i<6;i++)
int main () Prétraitement printf("Calcul N%d = %d", x*y+z);
debut par le return 0;
int x, y, z, i ; préprocesseur }
x = NMAX – 1;
y = 2*NMAX; 
z = NMAX;
for (i=0;i<NMAX;i++)
#ifdef TOTO
afficher("Calcul N%d = %d", calcul(x,y,z));
#else
afficher("Calcul N%d = %d", calcul(y,z,x));
#endif
return 0;
fin

– NB : Le fichier main.c généré par le préprocesseur n’est pas visualisable. Il passe directement à la
compilation à proprement dite.
© ESP, 2012 109

17 Le mode d’exécution Console et en Ligne de


commande (les paramètres de la fonction main)

© ESP, 2012 110

©Bull 2012 55
07/03/2017

Le mode d’exécution Console et en Ligne de commande

Un programme développé en C ou en tout autre langage peut être lancé de


diverses manières :
En mode console
– Depuis l’environnement de développement intégré
 Généralement en phase de tests, pour la validation du programme

– Un double-clic sur l’icone du fichier exécutable dans le répertoire de projet ou depuis


n’importe quelle arborescence ou le fichier exécutable a été déposé.

En ligne de commande
– L’exécution d’un programme en ligne de commande nécessite le lancement de l’invite de
commandes windows disponible dans le Menu Démarrer …
– Section détaillée en TP (Consultez le fichier de LAB)

© ESP, 2012 111

Merci pour votre attention

© ESP, 2012 112

©Bull 2012 56

Vous aimerez peut-être aussi