Vous êtes sur la page 1sur 110

Généralités

1. GENERALITES

1.1 Introduction - Historique

Le langage C est un langage de programmation conçu pour de multiples utilisations.


Son développement est parallèle au système UNIX. Le noyau du système UNIX est écrit en
langage C. Désormais, il est utilisé sur tous les systèmes d'exploitation et donc sur toutes les
machines.

Les principes fondamentaux du langage C sont issus du langage BCPL créé vers 1970
pour le premier système UNIX dans les laboratoires AT & T par Ken THOMPSON et Dennis
RITCHIE.
En 1970, Ken THOMPSON crée le langage B inspiré du BCPL.
En 1972, Dennis RITCHIE définit le langage C à partir des travaux de Ken
THOMPSON.

Ces travaux seront continués par Brian W Kernigham et DM Ritchie en 1972 pour
donner naissance au premier ouvrage de référence "Le langage C" Editions MASSON.

Si le noyau du langage C est assez restreint, il s'enrichit d'une librairie standard qui
contient des fonctions permettant les traitements les plus divers (Entrées/Sorties, Traitements
des chaînes de caractères, Gestion dynamique de la mémoire, etc...).

L'étude du langage C passe obligatoirement par l'étude complète du noyau.


Ultérieurement, vous pourrez aborder l'étude de la POO (Programmation Orientée Objet) en
C++.

Le langage C est un langage structuré, déclaratif et faiblement typé. Cette structuration


s'appuie sur quatre éléments:
• l'application
• les fichiers
• les fonctions
• les données

Des travaux de normalisation ont été entrepris à partir de 1983. Le C-ANSI a été
approuvé fin 1988 (Norme X3-159-1989).

Dans ce document, on s'efforcera d'utiliser la norme ANSI. Tous les exemples (sauf
avertissement) sont donnés pour un compilateur respectant la norme.

PS/LANGAGES Page 1
Généralités

1.2 Notions de fonctions et de blocs

Les unités de structuration du langage C sont:


- la fonction qui correspond à la notion de sous-programme en PASCAL,
FORTRAN ou ADA. Il n'y a pas de distinction entre procédure (qui effectue une
action) et fonction (qui calcule un résultat en fonction de paramètres).
- les fichiers comprenant des déclarations de fonctions et d'objets. Les fichiers
peuvent être compilés séparément. Ils constituent des modules, brique de base
dans la construction d'applications.

Un programme C, c'est donc un ou plusieurs fichiers comprenant:


- des déclarations de fonctions.
- des déclarations d'objets, variables ou constantes.
- des directives pour le préprocesseur.

Contrairement à PASCAL ou ADA, on ne peut déclarer de fonctions à l'intérieur d'une


autre fonction.

Une fonction est un module (ou sous programme) destinée à effectuer une opération
élémentaire et une seule, en définissant les cas limites. En langage C, un programme source
est constitué de fonctions dont une (appelée main) constitue le point d'entrée dans le
programme. On ne peut trouver qu'un seul 'main' dans un programme.

Un bloc est un ensemble d'instructions formant une entité logique indissociable bornée
par une accolade ouvrante '{' (début) et une accolade fermante '}' (fin).Le plus grand bloc est
la fonction.

fonction1(...);
fonctionN(...);
main() /* Point d'entrée */
{
Possibilités de variables locales
Code
}
fonction1(...)
{
Possibilités de variables locales
Code
}
fonctionN(...)
{
Possibilités de variables locales
Code
}

La fonction main est reconnue par l'éditeur de liens comme le point de départ de
l'exécutable.

PS/LANGAGES Page 2
Généralités

fic
hie
r1
.c fic
hie
r2
.c fic
hie
r3
.c

m ain
() fon c
tio
n1
() fon c
tio
nN()
{ { { F
ic
h ie
rs
... ... ... S
ources
} } }

C
om
pila
tio
n

fic
hie
r1
.o fic
hie
r2
.o fic
hie
r3
.o

F
ic
hie
rs
Obje
ts

L
ib
ra
irie
s
E
ditio
ndeL
ie
ns

Fich
ier
P
ro
gra
mme e
xéc
uta
ble

PS/LANGAGES Page 3
Généralités

1.3 Le compilateur c
Compilation et Edition de liens sont regroupés dans une seule commande qui, suivant
les options, enchaîne tout ou partie des phases suivantes:

S o u rce C $ c c f ic h ie r .c

v a a n a ly s e r to u te s le s d ir e c tiv e s c o m m e n ç a n t
cpp p a r le s ig n e #
v a é lim in e r to u t te x te c o m p r is e n tr e /* e t * /

S o u rce C f ic h ie r .i

cco m le c o m p ila te u r c v a g é n é r e r d u c o d e
s o u r c e a s s e m b le u r m a c h in e

S o u r c e A s s e m b le u r f ic h ie r .s

as A s s e m b le u r la n g a g e m a c h in e

C o d e O b je t f ic h ie r .o

ld E d ite u r d e lie n s e n tr e le c o d e o b je t
e t le s b ib lio th è q u e s s c r u té e s

C o d e E x é c u ta b le a .o u t

PS/LANGAGES Page 4
Généralités

1.3.1 La compilation sous UNIX


La commande de compilation sous UNIX est :
cc [options] liste de fichiers

Extension des fichiers


Fichiers sources .c
Fichiers compilables .i
Modules assembleur .s
Fichiers objets .o
Librairies statiques .a
Exécutable sans extension

Quelques options de la commande cc sur DPX20


cc fic1.c  exécutable a.out
cc fic1.c -o prog  exécutable prog
cc -O fic.c -o prog  exécutable optimisé prog
cc -c fic1.c  module objet fic1.o
cc -S fic1.c  source assembleur fic1.s
cc -P fic1.c  source compilable fic1.i
cc fic1.c fic2.c -o prog  exécutable prog constitué à partir des 2
fichiers sources fic1.c et fic2.c
cc fic1.o fic2.o -o prog  exécutable prog constitué à partir des 2
fichiers objets fic1.o et fic2.o
cc -lm fic1.c -o prog  exécutable prog en linkant la librairie
mathématique libm.a
cc -g fic1.c  exécutable a.out contenant des
informations de déboggage
cc fic.c -qsrcmsg  affiche la ligne source en erreur
marque les items en erreur dans la ligne
cc fic.c -qxref  produit un listing objet qui inclut les cross
reference dans fic.lst

Remarques : la librairie standard (libc.a) est linkée automatiquement.

1.3.2 La compilation sous TURBO C


Sous l'environnement de développement intégré (EDI), la compilation d'un fichier
source s'obtient par
- la commande Compile (raccourci : Alt F9) qui compile le fichier
- ou par la commande Make (raccourci F9) qui produit directement l'exécutable.

Il est également possible de compiler par l'utilitaire TCC (compilateur en ligne de


commande à partir de la ligne de commande MSDOS) en utilisant les nombreuses options
disponibles (cf documentation TURBO C de BORLAND).

Le TURBO C produit des fichiers objets d'extension .OBJ et des fichiers exécutables
d'extension .EXE.

PS/LANGAGES Page 5
Eléments de base du langage

2. ELEMENTS DE BASE DU LANGAGE

2.1 Les identificateurs

Un identificateur permet de nommer une variable, une pseudo-constante ou une


fonction. Ils doivent être écrits selon les règles suivantes :

- 32 caractères maximum (certains systèmes ne tiennent compte que des 8


premiers).
- le premier caractère doit obligatoirement être soit une lettre soit un souligné (à
éviter).
- les autres caractères peuvent être indifféremment des lettres (a-z), des chiffres
ou le souligné.
- le signe '-', l'espace, les caractères accentués ainsi que tous les caractères non
cités au paragraphe précédent sont interdits.
- en règle générale, le nom des variables est écrit en lettres minuscules et celui des
pseudo-constantes en majuscules (Conventions des programmeurs).
- le compilateur C fait la différence entre majuscules et minuscules.

Certains identificateurs sont interdits car ils constituent les mots réservés du langage.

2.2 Les mots réservés

Types Classes Intructions Autres


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

PS/LANGAGES Page 6
Eléments de base du langage

2.3 Les séparateurs


Les différents séparateurs reconnus par le compilateur peuvent avoir plusieurs
significations.
Type Nom Significations
[] Crochets Indice d'accès dans un tableau
() Parenthèses 1/ Groupement d'expressions (forcer la priorité)
2/ Isolement des expressions conditionnelles
3/ Déclaration des paramètres d'une fonction
4/ Conversion explicite d'un type (casting)
{} Accolades 1/ Début et fin de bloc d'instructions
2/ Initialisation à la déclaration d'un tableau
3/ Déclaration d'une structure
, Virgule Sépare les éléments d'une liste d'arguments
; Point virgule Terminateur d'instruction
: Deux points Indique une instruction avec label
. Point Permet l'accès à un champ d'une structure

2.4 Les commentaires

Les commentaires permettent de porter des remarques afin de faciliter la lecture d'un
programme source. Chaque commentaire est délimité par les combinaisons suivantes :

/* début de commentaire

*/ fin de commentaire
Les commentaires ne peuvent pas être imbriqués.
Les commentaires ne sont pas pris en compte par le compilateur et n'augmentent donc
pas la taille des programmes exécutables.

Remarque: en Turbo C et dans les versions les plus récentes, la séquence // permet de
mettre la ligne courante en commentaires.

PS/LANGAGES Page 7
Eléments de base du langage

2.5 Principales directives de compilation

2.5.1 Généralités
Avant de réaliser les opérations de compilation, le système utilise un outil appelé
préprocesseur qui exécute les directives de compilation placées dans le programme source.

Précédées du dièse (#), elles sont placées, de préférence, en tête du programme.

2.5.2 Inclusion de fichier


Pour fonctionner, un programme en langage C a besoin d'un certain nombre de
déclarations ou données stockées dans des fichiers d'en tête (.h). Il est donc nécessaire que ces
fichiers soient intégrés au programme source avant la compilation.

#include <fichier> ou #include "fichier"

Cette directive permet d'inclure des fichiers issus d'une bibliothèque lors de la
compilation.

Si le fichier à inclure est dans le répertoire 'include' ou 'usr/include', le nom du fichier


sera encadré par <...>, sinon le chemin d'accès du fichier est mis entre guillemets.

Exemples:
#include <stdio.h>
#include"ma_biblio/mon_fic.h"

2.5.3 Définition de pseudo-constante


#define expression

Cette directive permet de créer une pseudo-constante. Par convention, on écrit le nom
des pseudo-constante en lettres majuscules.

2.5.4 Définition de macro-instructions


Le préprocesseur permet la définition de macro-instructions.
Une macro-instruction est une définition comportant des paramètres nommés entre
parenthèses tout de suite après le nom de la macro.
Une macro s'utilise comme une fonction. Le programme est plus rapide (économie du
temps d'appel et de retour) mais plus gros.
Exemple:
#define maxi(a,b) ((a>b)?(a):(b))

Remarque: il faut mettre des parenthèses pour éviter tout problème de précédence des
opérateurs lors de l'utilisation de la macro dans une expression. Ce problème de précédence
des opérateurs sera vu au cours du chapitre 4 sur les opérateurs de base.

PS/LANGAGES Page 8
Eléments de base du langage

2.5.5 Compilations conditionnelles


On peut contrôler le fonctionnement du préprocesseur grâce à des instructions
conditionnelles qui sont évaluées au cours du pré-traitement.

2.5.5.1 Annulation de constante


#undef expression

Cette directive permet d'annuler l'effet d'un #define. Elle est surtout utilisée pour
remplacer les macro-instructions définies dans les fichiers d'entête.

Si l'expression n'a pas été définie, la directive n'a aucun effet.

2.5.5.2 Contrôle de définition


#ifdef expression
instructions
#endif

#ifndef expression
instructions
#endif

Ces deux directives permettent de vérifier si une expression a été (ifdef) ou n'a pas été
(ifndef) définie. Si la réponse est 'oui', les instructions qui suivent seront exécutées jusqu'à la
rencontre du #endif.

2.5.5.3 L'inclusion conditionnelle


#if <condition>
instructions_1
#else
instructions_2
#endif

Si condition est vraie, instructions_1 sera inclue, dans le cas contraire c'est
instructions_2.

#if <condition_1>
instructions_1
#elif <condition_2>
instructions_2
#endif

Si condition_1 est vraie, instructions_1 sera inclue. Dans le cas contraire, condition_2
sera évaluée, si elle est vraie instructions_2 sera inclue.

PS/LANGAGES Page 9
Eléments de base du langage

Exemple:
#if flag = = 1
#include "ficl.h"
#elif flag == 2
#include "fic2.h"
#else
#include "fic3.h"
#endif

2.6 Les constantes


Une constante est une donnée dont on ne peut modifier la valeur.

Les constantes symboliques sont déclarées en utilisant la directive de compilation


#define.

2.6.1 Les constantes entières


Exemples:
#define TINTIN 14 /* exprimée en décimal */
#define MILOU 0325 /* exprimée en octal */
#define DUPONT 0xd5 /* exprimée en hexadécimal */
#define DUPOND 0XD5 /* exprimée en hexadécimal */

Le programmeur peut demander que les constantes entières soient codées sur un long en
ajoutant la lettre L (ou l) à la fin de la valeur.

#define ASTERIX 14L

2.6.2 Les constantes réelles


Exemples:
#define PI 3.14159 /* notation décimale */
#define PI2 0.314e+1 /* notation scientifique */

Les constantes réelles sont associées à un codage en mémoire sur un double (8 octets).

2.6.3 Les constantes caractères


Exemple :
#define DOLLAR '$'

Les caractères peuvent être représentés par le caractère '\' suivi du code ASCII octal ou
par le caractère '\x' suivi du code ASCII hexadécimal.

Exemples:
#define BELL '\007' /* Code ASCII 007 en octal de la sonnerie */
#define ESCAPE '\033' /* Code ASCII 033 en octal : touche ESC */
#define CR '\x0d' /* Code ASCII 0d en hexadécimal : Return */
#define BS '\x08' /* Code ASCII 08 en hexadécimal : BackSpace */

PS/LANGAGES Page 10
Eléments de base du langage

Certains caractères particuliers sont représentés par le caractère \ suivi d'une lettre
symbolisant leur fonction.

Signification Mnémonique Code ASCII Symbole


Fin de ligne LF 0A \n
Tabulation horizontale HT 09 \t
Tabulation verticale VT 0B \v
Retour arrière BS 08 \b
Retour chariot CR 0D \r
Saut de page FF 0A \f
Signal sonore BEL 07 \a
Barre oblique inverse \ 5C \\
Guillemet " 22 \"
Apostrophe ' 2C \'
Caractère nul NUL 0 \0
Nombre octal ooo \ooo
Nombre hexadécimal hh \xhh

2.6.4 Les constantes chaînes


Une chaîne de caractères en C est encadrée par des doubles quotes.
Exemple:
#define TITRE "Bonjour et Bienvenue"

Observation: En mémoire, cette chaîne sera terminée par '\0'.


Remarque: pour insérer des caractères " ou \ dans une chaîne, on les fait précéder d'un
\.

2.7 Les variables


Comme tout langage déclaratif, le langage C exige que les variables soient déclarées
avant leur utilisation.

Une variable est définie par 3 attributs:


- son nom (l'identificateur de la variable)
- son type
- sa classe d'allocation en mémoire

Ces trois informations doivent se retrouver dans la déclaration de la variable (de


manière explicite ou non).

Déclaration :
[classe] [unsigned] <type> <identificateur>;

Exemples:
int i; /* déclaration d'une variable i de type int de classe auto */
/* (classe auto par défaut) */
static int nb; /* déclaration d'une variable nb de type int de classe static */

Remarque: la notion de classe sera revue au cours du chapitre suivant.

PS/LANGAGES Page 11
Eléments de base du langage

Les variables symboliques (i ou nb) permettent de stocker des valeurs et ont un type
associé. Il y a deux valeurs associées à une variable symbolique.
• La valeur de la donnée stockée en mémoire à une position donnée. On l'appelle
rvalue (right-value ou read-value).
• La valeur de cette position, c'est-à-dire l'adresse en mémoire où est stockée la
valeur. On l'appelle lvalue (left-value ou location-value).

Exemple : dans l'instruction suivante


i = i + 5;
la variable symbolique i apparaît à la fois du côté droit et du côté gauche de
l'opérateur =.
L'instance du côté droit est lue (read) mais pas modifiée, c'est une rvalue
L'instance du côté gauche est écrite (location), c'est une lvalue.

PS/LANGAGES Page 12
Eléments de base du langage

2.8 Structure d'un programme en langage C

Inclusions si nécessaire (#include)

Définition des pseudo-constantes ("#define")

Définitions de type

Prototypes des fonctions

Déclaration des variables globales

main() (point d'entrée du programme)

Déclaration des variables locales au main

Instructions

Type et nom de la première fonction (paramètres)

Déclaration des variables locales

Instructions

.../...

Type et nom de la nième fonction (paramètres)

Déclaration des variables locales

Instructions

PS/LANGAGES Page 13
Les types de base

3. LES TYPES DE BASE


Bien que le langage C soit faiblement typé, la notion de type est très présente.

• Tout objet possède un type et un seul, celui qui lui a été donné lors de la
déclaration.
• Un objet possède à un moment donné une valeur et une seule: celle-ci doit
appartenir à l'ensemble des valeurs déterminé par le type (Attention : le langage C ne le
vérifie pas toujours).
• Toute opération sur un objet doit appartenir à l'ensemble des opérations permises
par ce type.

3.1 Généralités-classification

3.1.1 Les types de base


Les types de base correspondent aux types directement supportés par la machine.

Les entiers
int entier
short entier court
long entier long
char caractère ASCII qui est un entier

Les réels
float réel en virgule flottante
double réel en virgule flottante double précision

Il n'existe pas de type booléen. Mais, un entier égal à zéro est considéré comme faux et
différent de zéro comme vrai.

3.1.2 Les types dérivés


• le type pointeur pour avoir des objets contenant l'adresse d'objets d'un type donné.
• le type tableau pour avoir des objets composés d'objets de même type.
• le type structure pour avoir des objets composés d'objets de types différents.
• le type union pour manipuler des objets de type différents sur une même zone
mémoire.
• le type fonction : objet particulier.
• le type énumération pour décrire un ensemble fini de valeurs entières.

3.1.3 Le type void


Le type void est un type particulier dans la mesure où il n'existe aucun objet de type
void. Il ne sert qu'a préciser qu'une fonction ne renvoie rien ou n'a pas de paramètre.
Exemples:
void imprime (int); /* la fonction imprime ne retourne aucune valeur */
void va_a_la_ligne (void); /* la fonction va_a_la_ligne ne retourne aucune valeur
et n'attend aucun paramètre*/

PS/LANGAGES Page 14
Les types de base

3.1.4 Les définitions de types par typedef


On dit aussi type synonyme. Le mot réservé typedef permet de définir un type
synonyme (en général une abréviation) pour un type existant.
Exemple:
typedef enum {FAUX,VRAI} booleen;
Permet de déclarer un synonyme (un alias) pour le type enum {FAUX,VRAI}.

Typedef sert beaucoup pour la documentation du programme et la réduction de la


complexité de notation d'un type dérivé. En cela, il améliore la lisibilité des définitions et
contribue à la portabilité (Exemple : les tailles des variables de type int selon la machine). Se
reporter au chapître 9 pour plus de précisions sur typedef.

3.2 Les types entiers


Ce sont des variables de type simple dont la taille et les limites varient en fonction de la
machine utilisée.

Déclaration :
[classe] [unsigned] <type> <nom>;

Observations: Une variable peut être déclarée signée (signed valeur par défaut), ou non signée
(unsigned ). Dans ce dernier cas, le bit de signe est interprété en tant que bit de valeur.

Si la variable est déclarée signée, le premier bit sera utilisé pour représenter le signe. Le
codage d'un nombre négatif est réalisé par la méthode du complément à deux.

Exemples:
unsigned int ent; /* déclaration de la variable ent de type entier non signé */
char a = '\n'; /* déclaration et initialisation de la variable */

Limites d'utilisation des variables en fonction des tailles

Type Dénomination Longueur Longueur Valeurs limites


UNIX DOS
int Entier 4 2
short Entier court 2 2 -32 768 à 32 767
unsigned short Entier court non signé 2 2 0 à 65535
long Entier long 4 4 -2 147 483 648 à 2 147 483 647
unsigned long Entier long non signé 4 4 0 à 4 294 967 295
char Caractère 1 1 -128 à 127
unsigned char Caractère non signé 1 1 0 à 255

En cas de dépassement de capacité lors de l'exécution, aucune erreur ne sera signalée


mais la valeur sera erronée.

Le fait que les variables de type char soient signées ou non dépend de la machine
utilisée mais les caractères imprimables sont toujours positifs.

PS/LANGAGES Page 15
Les types de base

3.3 Les réels

Type Dénomination Longueur Valeurs limites


float Réel 4 [+/-].701411E-38 à [+/-].701411E38
double Réel double précision 8 [+/-]1.0E-307 à [+/-]1.0E307
long double* Réel très grande précision 10 [+/-]3.4E-4932 à [+/-]1.1E4932

En cas de dépassement de capacité lors de l'initialisation, la valeur est considérée


comme + ou - la valeur minimale. Si cette erreur a lieu lors d'un calcul, l'exécution du
programme est interrompue avec affichage d'un message d'erreur.

* : le type long double n'est pas disponible sur tous les systèmes.

3.4 Les caractères


Ils sont codés sur 8 bits ( un octet ) et déclarés entre ' '.

Un caractère peut être déclaré non signé, dans ce cas, la plage des valeurs ASCII sera de
0 à 255.

3.5 Initialisation des variables


Exemples
main ()
{
int i, j = 3, k;
float x = 12000,
y = 1.2e4;
long n = 123L,
o = 132770;
char p1 = 'A',
p2 = '\x41', /* ou = 0x41*/
p3 = '\101', /* ou = 0101*/
p4 = 40;
int q = 10,
r = 010,
s = 0x10;
}

Toutes les déclarations de variables peuvent comporter le qualificatif const qui indique
que leurs valeurs ne seront jamais modifiées ou le qualificatif volatile qui demande au
compilateur de ne pas optimiser le code concernant cette variable.

const type <identificateur> = <valeur>;

volatile type <identificateur>;

exemples :
const int MAX = 100;
volatile int i;

PS/LANGAGES Page 16
Les types de base

3.6 Modèle mémoire d'un programme C

Cas général

Zone où sont placés dynamiquement (en cours


PILE d'exécution) les arguments passés aux
fonctions et les variables automatiques.
Zone de mémoire non allouée, disponible
TAS pour l'allocation dynamique.

Zone où sont placées (à la compilation) les


DONNEES variables externes et les variables internes
statiques.
Zone où sont placées les instructions qui
CODE constituent le programme.

Cas du C sous UNIX


Dans chaque fichier exécutable

EN-TETE En-tête dont l'adresse du


point d'entrée.
Références des fichiers utilisés
Section .TEXT Code exécutable. Fusions des sections
Zone contenant les données
Section .DATA correspondantes
static initialisées.
Zone contenant les données des modules objets
Section .BSS
static NON initialisées.
Commentaires des fichiers
Section .COMMENT
objets
Zone contenant les chaînes
Table des chaînes
de caractères
Table des symboles éventuellement

3.7 Classes d'allocation mémoire


Une variable est caractérisée par
- sa portée (visibilité) Remarque : à l'intérieur de cette portée, elle peut être
masquée par une déclaration plus interne
- sa durée de vie
- un lieu en mémoire

Le choix de la classe mémoire d'une variable est déterminé par les réponses aux trois
questions suivantes:
Quelle est la durée de vie de la variable ?
Quelle est sa visibilité ?
Où sera-t-elle stockée ?

PS/LANGAGES Page 17
Les types de base

Deux sortes de variables:


• les variables déclarées en dehors de toute fonction
= variables externes variable confidentielle : la portée est limitée au fichier
variable exportable (dans par un autre fichier)
• les variables locales à une fonction (ou un bloc)

Quatre sortes de mémoire

mémoire statique les variables restent vivantes pendant toute la durée


(zone de données) de vie du programme
mémoire dynamique (la pile) les variables sont empilées (dépilées) au rythme des
appels des fonctions.
les registres du processeur rapidité d'accès
le tas (heap) les variables sont créées dynamiquement

3.7.1 Les variables externes


On parle généralement de variables globales ou semi-globales.
Les variables globales sont déclarées à l'extérieur de toute fonction, sans mot clé, en tête
de fichier. Elles sont précédées du mot clé extern dans les autres fichiers en cas de
compilation séparée. Elles sont stockées dans la zone de données.
Les variables globales sont initialisées à 0 par défaut.

Exemple de variable globale

fic1.c fic2.c
int varglob; extern int varglob;
main() fonc()
{ {
varglob = 52; varglob = 55;
fonc(); ...
} }

Les variables semi-globales (ou confidentielles) sont déclarées en dehors de toute


fonction. Leur visibilité est le fichier dans lequel elles sont déclarées. Elles sont précédées du
mot clé static.
Exemple de variable semi-globale
fic1.c fic2.c
static int confident; /* aucune visibilité pour la
main() variable confident */
{ fonc2()
confident = 52; {
fonc1(); ...
} }
fonc1()
{
confident = 0;
...
}

PS/LANGAGES Page 18
Les types de base

3.7.2 Les variables locales


Les variables locales ne sont pas initialisées (valeur indéfinie) par défaut. Elles peuvent
l'être explicitement.

Les variables locales statiques ont la durée de vie du programme. Leur visibilité est
restreinte à la fonction de déclaration. Le contenu de la variable perdure entre chaque appel.
Elles sont déclarées avec le mot clé static et sont initialisées implicitement à 0.

Exemple:
fonc3()
{ Cette fonction affiche le
static int nb = 0; nombre de fois où elle a été
nb = nb + 1; appelée (nb n'est initialisé que
printf("Nombre d'appels = %d\n",nb); lors du premier appel).
}

Les variables locales automatiques sont des variables dont la durée de vie et la
visibilité sont celles de la fonction de déclaration. Ces variables sont créées automatiquement
à chaque appel et disparaissent à la fin de la fonction. Elles sont déclarées avec le mot clé
auto qui est facultatif. En effet, la classe auto est la classe par défaut des variables.

Exemples:
auto int i;
int k;

3.7.3 Les variables locales registres


Ce sont des cas particuliers des variables locales automatiques. Elles sont localisées
dans les registres du processeur quand cela est possible dans un objectif d'optimisation du
temps d'accès. Si l'utilisation des registres n'est pas possible, elles sont considérées comme
des variables locales automatiques. Elles sont déclarées avec le mot clé register. La
déclaration d'une telle variable reste une demande du programmeur. Il n'y a aucune assurance
que cette demande soit satisfaite.
Exemple:
register int i;
Remarques :
- Seuls les entiers, les caractères et les pointeurs peuvent être déclarés en register.
- On ne peut pas appliquer l'opérateur & à un objet déclaré de type register.

3.7.4 Tableau récapitulatif


DOMAINE
GLOBAL LOCAL
CLASSE Initialisation à 0 par le compilateur Initialisation à 0 pour les statiques
par défaut par défaut
Durée de vie du programme Durée de vie de la fonction ou du bloc
extern Stockée dans la zone de données
static Empêche l'exportation vers un autre Garde sa valeur d'un appel à l'autre
fichier
auto Classe implicite
register Placée dans un registre du processeur

PS/LANGAGES Page 19
Les types de base

3.7.5 Définition et déclaration d'une variable


En langage C, c'est au programmeur de faire la distinction entre définition et
déclaration. La définition entraîne une allocation mémoire alors que la déclaration signifie
utilisation. De façon schématique, on applique les règles suivantes:
• Quand une variable est initialisée, c'est une définition.
• Quand il n'y a pas d'initialisation et que le mot extern est présent, c'est une
déclaration.

3.8 Conversions de types


Contrairement à d'autres langages, le langage C autorise des instructions contenant des
opérandes de types variés.
Lorqu'une expression contient des opérandes de types différents, ils sont convertis en un
type commun. En général, les conversions d'un type 'étroit' en un type 'large' s'effectuent sans
pertes d'informations.
Des conversions se font également lors des affectations, la valeur de côté droit est
convertie dans le type de la valeur du côté gauche qui sera le type du résultat.
Aucun changement n'est interdit par le compilateur. Il revient au programmeur de
vérifier que les changements demandés ont une signification.

3.8.1 Combinaisons d'opérandes


Lorsque plusieurs opérandes de types variés se trouvent dans une expression, le
compilateur effectue un certain nombre de conversions en respectant les règles suivantes:

CHAR  systématique  INT  LONG  DOUBLE  LONG DOUBLE


FLOAT  systématique  DOUBLE  LONG DOUBLE

Fonctionnement général: si une expression contient au moins deux types de variables,


la variable du type le plus 'étroit' est convertie en variable du type supérieur.
Certaines conversions sont systématiques:
un caractère est toujours converti en entier.
un réel de type float est toujours converti en réel de type double.

3.8.2 Conversions lors d'assignations


Lors d'une assignation (variable = expression), la valeur de l'expression est affectée à la
valeur à gauche (left-value). Le compilateur effectue automatiquement les conversions si
nécessaire.

Conversions automatiques sans perte de précision et sans perte de signe


char ⇒ int le caractère est placé dans l'octet le moins significatif
int ⇒ long expansion du signe
int ⇒ float pas de problème
float ⇒ double pas de problème

Conversions automatiques avec perte de précision


int ⇒ char perte des octets les plus significatifs
long ⇒ int selon implémentation (pas de problème en UNIX)
float ⇒ int perte de la partie décimale
double ⇒ float perte de précision

PS/LANGAGES Page 20
Les types de base

3.8.3 Casting d'opérandes


Il est toujours possible d'imposer une conversion de type en préfixant l'opérande avec
un type placé entre parenthèse. C'est le transtypage ou casting.
Syntaxe : (type) expression
La conversion est temporaire et est faite aux risques du programmeur.
Exemple:
main()
{
int i = 3 , j = 2;
float x, y;
x = i / j; /* x a pour valeur 1 */
y = (float) i / j; /* y a pour valeur 1.5 */
}
Pendant la durée de l'évaluation, i est convertie en float.

Autre exemple:
main()
{
long n = 200000L;
double x;
...
x = sqrt((double)n);
/* la fonction sqrt réclame un paramètre de type double */
/* Il est donc nécessaire d'effectuer un transtypage */
}

PS/LANGAGES Page 21
Les opérateurs de base

4. LES OPERATEURS DE BASE

4.1 Les opérateurs arithmétiques

Addition +
Soustraction -
Multiplication *
Division / Si les deux opérandes sont de type entier, la division est une
division entière.
Si au moins un opérande est de type réel, la division est réelle.
Modulo % L'opérateur Modulo ne s'applique pas aux réels.

4.2 Les opérateurs de manipulations internes


Les opérateurs de manipulations internes permettent d'effectuer des opérations binaires
sur les bits d'un caractère ou d'un entier.

Symbole Rôle
& Et bit à bit
| Ou bit à bit
^ Ou exclusif bit à bit
~ Complément à un (inverse la valeur de chaque bit)
<< Décalage vers la gauche
>> Décalage vers la droite

Le décalage vers la gauche propage des 0 dans la variable. Cela correspond à une
multiplication par 2.
Le décalage vers la droite propage la valeur du bit de poids fort dans la variable. Cela
correspond à une division (entière) par 2.

4.3 L'opérateur d'affectation


C'est le signe =.
L'affectation multiple est possible:
L'évaluation se fait alors de la droite vers la gauche.
Exemple:
a = b = c = 0;

En langage C, la notion de variable n'est pas assez précise. Il faut introduire la notion de
lvalue (left-value), c'est-à-dire tout ce qui peut apparaître à gauche d'une affectation.

PS/LANGAGES Page 22
Les opérateurs de base

4.4 Combinaison d'opérateurs


L'opérateur d'affectation peut être associé à chacun des opérateurs précédents pour des
abréviations d'écriture.
x ope = i ⇔ x = x ope i
Exemples:
i += 20; ⇔ i = i + 20;
i -= 10; ⇔ i = i - 10;
k *= i; ⇔ k = k * i;
k /= i; ⇔ k = k / i;

4.5 Incrémentation / Décrémentation


Les opérateurs d'incrémentation et de décrémentation ne s'appliquent qu'à un seul
opérande.
i = ++j; pré-incrémentation ⇔ j = j + 1; puis i = j;
i = j++; post-incrémentation ⇔ i = j; puis j = j + 1;
i = --j; pré-décrémentation ⇔ j = j - 1; puis i = j;
i = j--; post-décrémentation ⇔ i = j; puis j = j - 1;

En préfixe, l'incrémentation ou la décrémentation est réalisée AVANT utilisation.


En suffixe, l'incrémentation ou la décrémentation est réalisée APRES utilisation.

Exemples:
au début de chaque ligne i vaut 3 et j vaut 15
équivalence résultat
i = ++j; j = j + 1; i = j; i = 16; j = 16;
i = j++; i = j; j = j + 1; i = 15; j = 16
i++; i = i + 1; i=4
j = ++i + 5; i = i + 1; j = i + 5; i = 4; j = 9
j = i++ + 5; j = i + 5; i = i + 1; i = 4; j = 8

4.6 Les opérateurs relationnels


Les opérateurs relationnels apparaissent dans des expressions booléennes qui prennent une des
deux valeurs VRAI ou FAUX.
En C, le VRAI est différent de 0 et le FAUX est égal à 0.

Symbole Rôle
> Strictement supérieur à
>= Supérieur ou égal à
< Strictement inférieur à
<= Inférieur ou égal à
== Egal à
!= Différent de

 Attention à l'erreur souvent rencontrée = (affectation) au lieu de == (comparaison)


dans une expression booléenne. Cette erreur est rarement signalée par les compilateurs
(quelques compilateurs avertissent au moyen d'un warning) car l'affectation est une
instruction possible même dans une expression booléenne.

4.7 Les opérateurs logiques


Symbole Rôle
|| Le résultat d'une somme logique est vrai si au moins un opérande est

PS/LANGAGES Page 23
Les opérateurs de base

vrai.
&& Le résultat d'un produit logique est vrai si tous les opérandes sont vrais.
! On appelle complément d'une variable x, la variable notée !x telle que :
x = 0 !x ≠ 0
x = 'A' !x ≠ 'A'

Remarques :
• dans le cas expr1 || expr2 : si expr1 est vraie, expr2 n'est pas évaluée.
• dans le cas expr1 && expr2 : si expr1 est fausse, expr2 n'est pas évaluée.

4.8 Opérateur ternaire ou opérateur conditionnel


a = expr1 ? expr2 : expr3 ;
Si expr1 est VRAI, on évalue expr2 sinon on évalue expr3
Exemple:
maximum = (a > b) ? a : b ;
maximum prend la valeur maximum entre a et b.

4.9 Opérateur séquentiel


exp1, exp2
Le but de cet opérateur , (virgule) est de garantir l'ordre d'évaluation des expressions
exp1 et exp2. La valeur retournée par cet opérateur est exp2.
Exemple :
resultat = (a=1, b=3, c=a+b);
resultat contient la valeur de c après évaluation de a=1 et b=3 soit 4.

4.10 Opérateurs d'adressage


Ces opérateurs sont liés à la notion de pointeurs.
Symbole Rôle
& Adresse de
* Contenu de l'objet pointé par

4.11 L'opérateur sizeof


sizeof donne la taille en octets de l'opérande
sizeof(objet) ou
sizeof(type)
Le résultat est de type size_t défini dans le fichier stddef.h (type long en général).
Cet opérateur est indispensable pour assurer la portabilité des programmes.

PS/LANGAGES Page 24
Les opérateurs de base

4.12 Autres opérateurs


Ces opérateurs sont liés à la notion de structure.
Symbole Rôle
. Membre de la variable
-> Membre de la variable pointé par

4.13 Priorités des opérateurs


Les règles de priorité et d'associativité fixent l'ordre d'évaluation des différents
opérateurs au sein d'une expression.

Priorité Opérateurs Signification Associativité


15 () Expression de gauche à droite
[] Indice
-> Membre d'une structure pointée
. Membre d'une structure
14 ! Non logique de droite à gauche
~ Complément à un
++ Incrémentation
-- Décrémentation
+- Signe (opérateur unaire)
(type) Casting
* Elément pointé
& Adresse de
sizeof() Taille de
13 * Multiplication de gauche à droite
/ Division
% Modulo
12 + Addition de gauche à droite
- Soustraction
11 << Décalage à gauche de gauche à droite
>> Décalage à droite
10 < Inférieur de gauche à droite
> Supérieur
<= Inférieur ou égal à
>= Supérieur ou égal à
9 == Egal à de gauche à droite
!= Différent de
8 & ET bit à bit de gauche à droite
7 ^ OU exclusif bit à bit de gauche à droite
6 | OU bit à bit de gauche à droite
5 && ET logique de gauche à droite
4 || OU logique de gauche à droite
3 ?: Expression conditionnelle (ternaire) de droite à gauche
2 = Affectation de droite à gauche
+=, *=, /=, ^=, &=, <<=, >>=, Affectations diverses
1 , Opérateur séquentiel de gauche à droite

Dans le cas où deux opérateurs se trouvent au même niveau de priorité, la priorité est
relative au sens d'évaluation.

L'ordre d'évaluation des opérandes est quelconque en C et n'est pas influencé par les
parenthèses sauf pour les opérateurs &&, ||, ?:, et ,.
Exemple:

PS/LANGAGES Page 25
Les opérateurs de base

L'écriture a[i] = i++ est incorrecte car on ne sait pas si i est incrémenté avant
d'accéder au tableau ou après.
L'écriture correcte serait:
a[i] = i;
i++; /* ou l'inverse suivant ce que désire le programmeur */

Autre exemple d'écriture incorrecte


i = 0;
while (i < MAX)
dest[i] = source[i++];
Il faut écrire
i = 0;
while (i < MAX)
{ dest[i] = source[i];
i++;
}
Ces absences de spécification ne sont pas une faiblesse du C mais une force. Pour tirer
le meilleur parti du matériel, C laisse la décision au fabricant.

Il vaut mieux ne pas écrire de code qui dépende de l'ordre d'évaluation pour
garder une bonne portabilité.

4.14 Remarques sur les règles de précédence


Soit les expressions suivantes:
a = b = c = 2;
Associativité de droite à gauche
a = b = ( c = 2 );
a = ( b = ( c = 2 ) );
( a = ( b = ( c = 2 ) ) );

a | b & c * d;
Associativité de gauche à droite mais priorités décroissantes : *:(13); &:(8); |:(6)
a | b & ( c * d );
a | ( b & ( c * d ) );
( a | ( b & ( c * d ) ) );

a || b || c || d;
Associativité de gauche à droite
( a || b ) || c || d;
( ( a || b ) || c ) || d;
( ( ( a || b ) || c ) || d );

PS/LANGAGES Page 26
Les entrées-sorties sur les voies standards

5. LES ENTREES - SORTIES SUR LES VOIES STANDARDS

5.1 Généralites
Le langage C n'est pas doté d'instructions spécifiques d'entrée ou de sortie. Il gère ses
entrées et sorties comme des flux de données.
Les systèmes d'exploitation ouvrent automatiquement des pseudo fichiers.
stdin clavier
stdout écran
stderreur fichier de sortie d'erreur standard (écran)

En plus, DOS ouvre


stdaux sortie série
stdprn sortie imprimante

Le langage C met en place pour certaines fonctions des buffers. Ces buffers sont
remplis à partir du buffer système correspondant. Le buffer C n'est lu que lorsque l'utilisateur
en fait la demande (Touche ENTER) ou en effectuant un vidage du buffer.

L'utilisation des fonctions d'entrées/sorties nécessite l'inclusion du fichier stdio.h qui


contient les prototypes de ces fonctions.

5.2 Les sorties mises en forme


Les fonctions printf s'occupent de mettre en forme les données en sortie.

int fprintf(FILE *stream, const char *format,[arguments]);


fprintf convertit ses arguments d'après les spécifications du format, et écrit le résultat
sur le flot stream. Elle retourne le nombre de caractères écrits ou une valeur négative en cas
d'erreur.

int printf(const char *format,[arguments]);


printf équivaut à fprintf(stdout,const char * format,[arguments]);

int sprintf(char *s,const char *format,[arguments]));


sprintf est similaire à printf, mais le résultat est écrit dans la chaîne de caractères s et
terminé par '\0'. Elle retourne le nombre de caractères écrits, non compris le '\0'.

arguments est la liste des :


- variables,
- expressions arithmétiques,
- des fonctions qui renvoient une valeur.

- il doit y avoir autant de formats que d'arguments,


- à l'exécution de l'instruction, la valeur de chaque argument est affichée en
remplacement de son format. La correspondance est effectuée par position.

PS/LANGAGES Page 27
Les entrées-sorties sur les voies standards

Composition de la chaîne format:

%[drapeaux][largeur][.précision][interprétation du type]caractère de conversion


La chaîne de caractères format contient des caractères ordinaires et des spécifications de
conversion, dont chacun provoque la conversion et l'impression de l'un des arguments.
Chaque spécification de conversion commence par le caractère % et se termine par un
caractère de conversion. Entre les deux, on peut placer dans l'ordre des drapeaux, une largeur,
une précision, une interprétation du type.

Caractères de conversion

Caractère Type de l'argument Converti en


d, i int notation décimale signée
o int notation octale non signée
u int notation décimale non signée
x, X int notation hexadécimale non signée en utilisant abcdef
pour x ou ABCDEF pour X
f double notation décimale de la forme : [-]mmm.ddd, où le
nombre de d est donné par la précision (6 par
défaut); si la précision vaut 0, le point décimal est
supprimé
e, E double notation décimale de la forme [-]m.ddd e[+/-]xx ou
[-]m.ddd E[+/-]xx où le nombre de d est donné par
la précision
g, G double l'impression se fait suivant le format %e ou %E si
l'exposant est inférieur à -4 ou supérieur ou égal à la
précision; sinon suivant %f. Les zéros ou le point
décimal à la fin ne sont pas imprimés
c int un seul caractère, après conversion en unsigned char
s char * les caractères d'une chaîne sont imprimés jusqu'au
'\0' ou après avoir imprimé le nombre de caractères
indiqué par précision
p void * écrit l'argument suivant le format du type pointeur
n int * le nombre de caractères écrits jusqu'à présent est
écrit dans l'argument. Ne convertit pas d'argument
% imprime un %

Drapeaux :
- (moins) cadre l'argument converti à gauche, dans son champ d'impression.
+ (plus) imprime systématiquement le signe du nombre.
espace si le premier caractère n'est pas un signe, place un espace au début.
0 pour les conversions numériques, complète le début du champ par des
zéros.
# spécifie un format de sortie différent. Pour o, le premier chiffre sera 0.
Pour x ou X, le préfixe correspondant 0x ou 0X si le résultat est non nul.
Pour e, E, f, g, et G, la sortie comportera un point décimal. Pour g et G, les
zéros de terminaison seront conservés.

PS/LANGAGES Page 28
Les entrées-sorties sur les voies standards

Largeur fixe la largeur minimale (signe compris), du champ d'impression, cadrage


à droite. Si l'argument possède moins de caractères que le nombre indiqué,
il sera complété par des caractères de remplissage (0 ou espaces).

Précision précédé d'un point, le nombre maximal de caractères à afficher à droite du


point décimal.

Interprétation du type
h short int pour d, i, o, u x
l long int pour d, i, o, u, x
l double pour E, e, f, g, G
L long double

PS/LANGAGES Page 29
Les entrées-sorties sur les voies standards

Exemples d'utilisations de printf


Programme Résultat
#include <stdio.h>
main()
{ char chaine[10]="Monsieur";
int i;

printf("%d\n",-12); -12
printf("%5d\n",-12); bb-12
printf("%05d\n",-12); -0012
printf("%-5d\n",-12); -12bb
printf("%u\n",-12); 4294967284
printf("%o\n",12); 14
printf("%o\n",-12); 37777777764
printf("%x\n",12); c
printf("%#x\n",12); 0xc
printf("%#o\n",12); 014
printf("%0X\n",12); C
printf("%X\n",-12); FFFFFFF4
printf("%f\n",3.142); 3.142000
printf("%3f\n",3.142); 3.142000
printf("%#f\n",3.142); 3.142000
printf("%3.2f\n",3.142); 3.14
printf("%1.2f\n",31.427); 31.43
printf("%+1.2f\n",31.427); +31.43
printf("%+1.2e\n",31.427); +3.14e+01
printf("%+5.1E\n",31.427); +3.1E+01
printf("%1.3g\n",31.427); 31.4
printf("%#g\n",31.427000); 31.4270
printf("%+5.1g\n",31.427); +3e+01
printf("%+5.2g\n",31.427); bb+31
printf("%c\n",'a'); a
printf("%3c\n",'a'); bba
printf("%-3c\n",'a'); abb
printf("%d\n",'a'); 97
printf("%x\n",'a'); 61
printf("%s\n","Bonjour, M"); Bonjour, M
printf("%4s\n","Bonjour, M"); Bonjour, M
printf("%.4s\n","Bonjour, M"); Bonj
printf("%-4s\n","Bonjour, M"); Bonjour, M
printf("%.20s\n","Bonjour, M"); Bonjour, M
printf("%10s\n","Bonjour, M"); Bonjour, M
printf("%-10s\n","Bonjour, M"); Bonjour, M
printf("%10.4s\n","Bonjour, M"); bbbbbbBonj
printf("%-10.4s\n","Bonjour, M"); Bonjbbbbbb
printf("%s\n",chaine); Monsieur
printf(chaine); Monsieur
printf("\nBonjour %n, M",&i); Bonjour , M
printf("\nla valeur de i est : %d",i); la valeur de i est : 9
}
b représente le caractère espace Réalisation sur DPX20

PS/LANGAGES Page 30
Les entrées-sorties sur les voies standards

Cas d'erreurs

Dans le cas où le nombre d'arguments ne correspond pas au format, C cherche toujours


à satisfaire le contenu du format.

printf ("%s",p,q ); ⇒ q ne sera pas traité.

printf ("%d %d",p ); ⇒ affichage de deux valeurs l'une juste l'autre indéterminée.

5.3 Les entrées mises en forme


Les fonctions scanf convertissent les données en entrée suivant un format

int fscanf(FILE *stream, const char *format, [arguments]);


fscanf lit les données du flot stream d'après les spécifications de format et affecte les
valeurs converties aux arguments suivants, chacun de ceux-ci devant être un pointeur. Elle
rend la main quand toute la chaîne format a été parcourue et retourne EOF si une erreur est
survenue sinon le nombre d'objets convertis et affectés.

int scanf(const char *format, [arguments]);


scanf équivaut à fscanf(stdin,const char * format, [arguments]);

int sscanf(char *s,const char * format, [arguments]);


sscanf est similaire à scanf, mis à part que les caractères en entrée sont extraits de la
chaîne de caractères s.

La chaîne de caractères format contient des spécifications de conversion utilisées pour


diriger l'interprétation de l'entrée. Elle peut contenir:
• Des espaces ou des caractères de tabulation qui seront ignorés.
• Des caractères ordinaires dont chacun est supposé s'identifier au caractère suivant
du flot d'entrée.
• Des spécifications de conversion, composées d'un %, d'un caractère facultatif de
suppression d'affectation (*), d'un nombre facultatif donnant la largeur maximale du champ,
des caractères h, l, L indiquant la largeur de l'emplacement de réception et d'un caractère de
conversion.

PS/LANGAGES Page 31
Les entrées-sorties sur les voies standards

Caractères de conversion

Caractère Type de l'argument Converti en


d int * Entier sous forme décimale
i int * Entier pouvant être sous forme octal si précédé de 0,
ou sous forme hexadécimale si précédé de 0x ou 0X
o int * Entier sous forme octale
u unsigned int* Entier non signé sous forme décimale
x int * Entier sous forme hexadécimale
e, f, g float * Nombre en virgule flottante
c char * Les caractères suivants en entrée sont placés dans le
tableau indiqué jusqu'à la largeur du champ (par
défaut 1)
s char * Chaîne de caractères ne contenant pas d'espace. Le
caractère '\0' sera ajouté.
p void * Pointeur comme l'imprimerait printf("%p").
n int * Ecrit dans l'argument le nombre de caractères lus
jusqu'à présent par cet appel de scanf.
[...] char * S'identifie à la plus longue chaîne de caractères en
entrée composée de caractères faisant partie de
l'ensemble entre crochets. Un caractère '\0' est
ajouté.
[^...] char * S'identifie à la plus longue chaîne de caractères en
entrée composée de caractères ne faisant pas partie
de l'ensemble entre crochets. Un caractère '\0' est
ajouté.

Les caractères de conversion d, i, n , o, u et x peuvent être précédés de h si l'argument


est un pointeur sur un short ou par l si l'argument est un pointeur sur un long.

Les caractères de conversion e, f, et g peuvent être précédés de l si l'argument est un


pointeur sur un double ou par L si l'argument est un pointeur sur un long double.

PS/LANGAGES Page 32
Les entrées-sorties sur les voies standards

Exemples d'utilisations de scanf


Tous les appels à scanf sont précédés d'un appel à la fonction fflush(stdin) permettant
de vider le buffer (précaution très utile).

Programme Saisie Résultat


#include <stdio.h>
main()
{
int i,a,b,h,m,s;
unsigned short sh;
char c,d;
char tab[20];

scanf("%d",&a); 1234 a = 1234


scanf("%2d",&a); 1234 a = 12
scanf("%2d%2d",&a,&b); 123456 a = 12 b = 34
scanf("%d",&a); 1234abc a = 1234
scanf("%d",&a); abc1234 a indéterminé
scanf("%d,%d",&a,&b); 12,34 a = 12 b = 34
scanf("%d%d",&a,&b); 12b34 a = 12 b = 34
scanf("%dplus%d",&a,&b); 3plus4 a=3b=4
scanf("%c%c",&c,&d); xby c = 'x' d = 'b'
scanf("%c%c",&c,&d); xyz c = 'x' d = 'y'
scanf("%cb%c",&c,&d); xby c = 'x' d = 'y'
scanf("%2c%c",&c,&d); xyz c = 'x' d = 'z'
scanf("%*2c%d",&a); 1997 a = 97
i=scanf("%d%*s%d%*s%d", 12heuresb30minutesb10sec h = 12 m = 30 s = 10
&h,&m,&s); i=3
i=scanf("%[ON]",&c); Y c indéterminé i = 0
i=scanf("%[ON]",&c); O c = 'O' i = 1
i=scanf("%[ON]",&c); N c = 'N' i = 1
scanf("%s",tab); Bonjour, Maître tab = 'Bonjour,'
scanf("%[^\n]",tab); Bonjour, Maître tab = 'Bonjour, Maître'
scanf("%hu",&sh); 35000 sh = 35000
scanf("%hu",&sh); 70000 sh = 4464
}
b représente le caractère espace Réalisation sur DPX20

L'oubli de l'opérateur d'adresse & est dangereux et indétectable pour le


compilateur: la valeur lue est écrite n'importe où.

PS/LANGAGES Page 33
Les entrées-sorties sur les voies standards

Fonctionnement du scanf
La fonction est mise en oeuvre dès que le retour chariot est frappé. Elle analyse les
caractères saisis au clavier jusqu'à ce qu'elle rencontre un type incompatible ou que la largeur
maximale est atteinte. Elle stocke la valeur dans l'argument correspondant (c'est pour cela
qu'elle doit connaître son adresse) et reprend l'analyse pour l'argument suivant.

La fonction est interrompue dès qu'un caractère saisi est incompatible avec l'argument
courant.

En cas de saisie d'une chaîne de caractères, le caractère '\0' est ajouté en fin de chaîne.

La fonction traite les données à partir du buffer. Si à la fin de l'exécution du scanf, le


buffer n'est pas vide, les informations sont conservées et traitées lors d'un autre appel d'un
scanf (ou de toute autre fonction d'entrée).

D'où la nécessité de faire appel presque systématiquement à fflush(stdin) avant


chaque appel à une fonction d'entrée utilisant le buffer.

Cas d'erreurs
Dans le cas où le nombre d'arguments ne correspond pas au format, C cherche toujours
à satisfaire le contenu du format.
Si la taille de l'argument est plus grande que le format, la valeur obtenue sera erronée,
dans le cas inverse, l'emplacement mémoire consécutif sera écrasé.
Exemple:
#include <stdio.h>
main()
{
char tab1[10] = "", tab2[10] = "";
scanf("%s",tab1);
}
A l'exécution, on saisit "abcdefghijklmnopq"
tab1 contient "abcdefghij"
tab2 contient "mnopq"

5.4 Les fonctions d'entrées-sorties de caractères

int fgetc(FILE *stream);


fgetc retourne le caractère suivant du flot stream, lu comme un unsigned char (converti
en int) ou bien EOF si erreur ou fin de fichier.

char * fgets(char *s, int n, FILE *stream);


fgets lit au plus les n-1 caractères suivants du flot stream et les place dans le tableau s.
Le caractère '\0' est copié dans le tableau.

int fputc(int c, FILE *stream);


fputc écrit le caractère c (converti en unsigned char) sur le flot stream et retourne le
caractère écrit ou EOF.

PS/LANGAGES Page 34
Les entrées-sorties sur les voies standards

int fputs(const char *s, FILE *stream);


fputs écrit la chaîne de caractères sur le flot stream. Elle retourne une valeur positive ou
nulle ou EOF en cas d'erreur.

int getc(FILE *stream);


getc équivaut à fgetc mis à part que si c'est une macro, elle peut évaluer stream
plusieurs fois.

int getchar(void);
getchar équivaut à getc(stdin). C'est une macro définie dans stdio.h

char *gets(char *s);


gets lit la ligne suivante en entrée et la place dans le tableau s. Elle remplace le
caractère de fin de ligne par '\0'. Cette fonction est souvent plus avantageuse pour la lecture
d'une chaîne de caractère car elle ignore les espaces contrairement au scanf.

int putc(int c, FILE *stream);


putc équivaut à fputc.

int putchar(int c);


putchar équivaut à putc(c, stdout). C'est une macro définie dans stdio.h.

int puts(const char *s);


puts écrit la chaîne de caractères s et un caractère de fin de ligne sur stdout.

int ungetc(int c, FILE *stream);


ungetc remet c (en unsigned char) sur le flot stream, où il sera retrouvé à la prochaine
lecture. On ne peut remettre EOF dans le flot.

PS/LANGAGES Page 35
Les entrées-sorties sur les voies standards

5.5 Séquences de contrôle ansi


En plus des codes ASCII, il est possible de gérer l'écran et le curseur en utilisant un
ensemble de codes dits "codes ANSI". Ces codes sont reconnus par les ordinateurs en
chargeant un pilote spécifique (ANSI.SYS sous DOS).

Les principaux codes ANSI sont les suivants:

Rôle Code ANSI


Effacement ligne x1B[K Efface à partir du curseur
Effacement écran x1B[2J
Positionnement du curseur x1B[l;cH Déplace le curseur à la position
l : numéro de ligne
c : numéro de colonne
Déplacement du curseur
- vers le haut x1B[#A Déplace de curseur de # lignes vers le haut
- vers le bas x1B[#B Déplace de curseur de # lignes vers le bas
- vers la droite x1B[#C Déplace le curseur de # colonnes à droite
- vers la gauche x1B[#D Déplace le curseur de # colonnes à gauche
Couleurs des caractères x1B[#m 30 Noir
31 Rouge
32 Vert
33 Jaune
34 Bleu
35 Magenta
36 Cyan
37 Blanc
Couleurs de fond x1B[#m 40 Noir
41 Rouge
42 Vert
43 Jaune
44 Bleu
45 Magenta
46 Cyan
47 Blanc
Attributs des caractères x1B[#m 0 Aucun
1 Gras
2 Réduit
3 Italique
4 Souligné
5 Clignotant
6 Rapide
7 Inverse
8 Caché

Exemples : printf("\x1B[2J") { efface l'écran }


ou printf("\33[2J"); { efface l'écran }

Remarque : Sous TURBO C, ces possibilités sont rarement utilisées car la bibliothèque
de TC fournit des fonctions d'affichage performantes dont les prototypes sont dans conio.h.

PS/LANGAGES Page 36
Les intructions en C

6. LES INSTRUCTIONS EN C
Le corps d'un programme est composé d'instructions. Ces instructions peuvent être de
deux types:
- les instructions simples.
- les instructions composées.

Les instructions simples sont terminées par un point virgule. On peut les écrire sur
plusieurs lignes (déconseillé) en indiquant le saut de ligne par un antislash. Elles
correspondent à des affectations ou des appels de fonctions.
instruction;

Les instructions composées sont des séquences d'instructions simples encadrées par des
accolades. Il s'agit en fait de la notion de bloc.
{ instruction; instruction; ...instruction; } ou
présentation plus claire et conseillée
{
instruction;
instruction;
...
instruction;
}

Dans tout le chapitre, lorsque l'on emploiera le terme <instruction>, on désignera une
instruction simple ou une instruction composée.

Une instruction de contrôle est une instruction qui permet de rompre l'exécution
séquentielle du programme.

6.1 L'instruction if-else


if (condition)
<instruction1>
[else
<instruction2>]

Remarques:
- la condition est obligatoirement entre parenthèses.
- la clause else si elle existe se rapporte au if le plus proche.

Exemples:

Instructions Exécution
int i = 3, j = 5;
if (i <j)
printf ("%d < %d ", i, j); 3<5
int i = 30, j = 5;
if (i <j)
printf ("%d < %d ", i, j);
else
printf ("%d >= %d ", i, j); 30 >= 5

PS/LANGAGES Page 37
Les intructions en C

Autre exemple:

int nbcoeff;
float somme_notes, moyenne;
...
if (nbcoeff != 0)
{
moyenne = somme_notes / nbcoeff;
printf("La moyenne est : %5.2f\n", moyenne);
}
else
{
printf("Calcul de la moyenne impossible\n");
printf("Recommencez\n");
}

6.2 L'instruction d'aiguillage switch


Le switch est une instruction de choix multiple qui effectue un aiguillage direct vers des
instructions en fonction d'une valeur discrète (résultat de l'expression).

switch (expression)
{ case expression_constante1 : <instruction>
case expression_constante2 : <instruction>
...
[default : <instruction>]
}

Les différents cas possibles servent d'étiquette; lorsque le traitement d'un cas est
terminé, l'exécution continue par le traitement du cas suivant jusqu'à ce que l'on sorte
explicitement du switch.. On sort généralement du switch grâce aux instructions break ou
return.

Expression doit être d'un type entier (ou caractère).


Expression_constante est une constante entière et doit être unique.
Si plusieurs valeurs correspondent à la même séquence d'instructions, les "case" sont
énumérés les uns à la suite des autres.
Si l'instruction default est présente, elle doit contenir obligatoirement au moins une
instruction.
Exemple:
switch(jour) /* jour =1 lundi; jour = 2 mardi etc...*/
{ case 1:
case 2:
case 3 :
case 4 :
case 5 : puts("Au travail !");
break;
case 6 : puts("Au jardin et ");
case 7 : puts("Repos");
break;
default : puts("Jour de la semaine non valide");
}

PS/LANGAGES Page 38
Les intructions en C

6.3 La boucle while


while (expression) <instruction>
Tant que la condition est réalisée (condition non nulle), l'instruction est exécutée.
L'instruction évalue expression avant de commencer la boucle. Si expression vaut 0 au
départ, l'instruction ne sera pas exécutée.

Exemples:
n = 100;
while (n > 0) /* Cette instruction provoque l'exécution */
{ instruction1; /* des instructions 100 fois avec n initial valant 100 */
instruction2;
n--;
}

n = 100;
while (n--) /* Cette instruction provoque l'exécution */
{ instruction1; /* des instructions 100 fois avec n initial valant 99 */
instruction2;
}

6.4 La boucle for


for(expr1 ; expr2 ; expr3)
<instruction>
Cette boucle peut être remplacée (sauf cas d'utilisation de continue) par la précédente de
la façon suivante:
expr1;
while (expr2)
{ <instruction>
expr3;
}
En général, expr1 et expr3 sont des affectations ou des appels de fonction et expr2 est
une expression booléenne.
Aucune des trois expressions n'est obligatoire, mais les points virgules devront toujours
être présents.
Lorsque expr2 est absente, elle est équivalente à 1 (VRAI).

Exemples :
int i, tableau[10];
for(i = 0; i < 10; i++)
tableau[i] = 0;

for(;;); /* boucle infinie */

Dans le cas général, attention à ne pas mettre de ; après le for car le ; termine
l'instruction donc le for.

PS/LANGAGES Page 39
Les intructions en C

6.5 La boucle do...while


do
<instruction>
while (expression);

Au contraire du while et du for qui testent leur condition d'arrêt en tête de boucle, le do
while la teste à la fin, après chaque passage dans le corps de la boucle qui s'exécute donc au
moins une fois.

Exemple :
int i = 0;
do
{
i--; Exécution
printf("i = %d\n", i); Affiche i = -1
} while (i > 0);

6.6 Les instructions break et continue (sauts associées aux boucles)


L'instruction break
L'instruction break fournit un moyen de sortir (passer à l'instruction suivant la boucle).
Elle ne permet cependant que de sortir de la boucle la plus interne.

Exemple:
int i, tableau[10];
for (i = 0; i < 10; i++)
{
if (tableau[i] == 0)
break; /* sortie du for si tableau[i] == 0 */
tableau[i] = tableau[i] + 1;
}

L'instruction continue
l'instruction continue fait débuter l'itération suivante de la boucle, en sautant la
séquence d'instructions comprise entre le continue et la fin de la boucle.

Exemple:
int i, tableau[10];
for (i = 0; i < 10; i++)
{
if (tableau[i] == 0)
continue; /* on passe à l'élément suivant (si i < 10) */
tableau[i] = tableau[i] + 1;
}

PS/LANGAGES Page 40
Les intructions en C

6.7 L'instruction return


return [expression];
L'instruction return permet de sortir d'une fonction.

Exemples:
return; /* la fonction s'interrompt et rend la main à la fonction appelante */

return expression; /* renvoie la valeur de l'expression à la fonction appelante */

6.8 L'instruction goto


goto label;
L'instruction goto est associée à un identificateur symbolique spécifiant l'endroit où doit
être effectué le branchement inconditionnel.

Exemple:
...
goto label;
...
label: ...

Son emploi doit être évité au maximum car contraire à l'esprit de programmation
structurée.

PS/LANGAGES Page 41
Les fonctions

7. LES FONCTIONS

Une fonction est un sous-programme qui reçoit éventuellement des arguments en entrée
(ces arguments sont toujours des valeurs) et qui retourne éventuellement une valeur d'un
certain type vers la fonction appelante.

L'écriture d'une fonction se fait en plusieurs étapes:


• On définit ce dont elle a besoin en entrée pour effectuer la tâche qui lui incombe
et ce qu'elle retourne en sortie.
• L'étape suivante consiste à définir le prototype. Le prototype indique notamment
le nombre et les types des arguments nécessaires ainsi que le type du résultat renvoyé. Le
prototype est déclaré avant la définition de la fonction. Il permet au compilateur de contrôler
la cohérence des appels.
• Enfin, la définition de la fonction consiste à écrire le corps de la fonction (coder
le traitement attendu).

Cette définition peut être placée dans le même fichier source que la fonction appelante
ou dans un autre fichier.
Il n'y a pas de possibilité d'imbrication des fonctions.

7.1 Définition de fonction


Syntaxe d'une fonction:
[type-de-retour] nom-de-fonction([déclarations d'arguments])
{
bloc
}

Type de retour
Cette donnée indique le type du résultat renvoyé par la fonction. Ce type peut être
simple (int, char ...) , une adresse (pour les tableaux) ou un type structuré.
Si la fonction ne renvoie aucun résultat, on utilise le type 'void'.
S'il n'est pas précisé. le type d'une fonction est par défaut de type int.

Nom-de-fonction
Le nom d'une fonction peut être n'importe quel identificateur valide.

Déclarations d'arguments
Ce sont les données venant de l'extérieur qui sont nécessaires à l'exécution de la
fonction. Ils sont placés entre parenthèses. Dans tous les cas, ces dernières devront être
présentes. La position des paramètres est primordiale.
Si la fonction reçoit des paramètres, ils seront déclarés sous la forme:
type <identificateur>, type <identificateur>...

Il est bien évident que le type déclaré dans la fonction appelée doit être le même que
dans la fonction appelante.

PS/LANGAGES Page 42
Les fonctions

Chaque paramètre est séparé d'un autre par une virgule.

Les paramètres sont :


- de la classe automatique.
- locaux à la fonction où ils sont déclarés.
- créés par recopie dans la pile.
- détruits à la fin de l'exécution de la fonction.

Bloc de la fonction
Celui ci commence par une accolade ouvrante et se termine par une accolade fermante.
A l'intérieur, on trouve, dans l'ordre :
1- La déclaration des variables locales.
2- Les instructions (ou blocs d'instructions) de la fonction.

7.2 Appel d'une fonction


Une fonction est appelée par son nom suivi de deux parenthèses (obligatoires)
contenant éventuellement des paramètres effectifs. Ces derniers peuvent être soit des
variables, soit des constantes, soit des expressions.
Exemples:
fonct1();
fonct2(a, 3);
resultat = fonct3(i, j);
fonct4(k+2, 4);

7.3 Passage de paramètres


Les paramètres sont initialisés automatiquement avec les valeurs passées par l'appelant.
A l'appel de la fonction avec les paramètres réels (effectifs), ceux-ci sont recopiés
dans les paramètres formels (de la fonction) et celle-ci travaille sur ces copies locales
stockées dans la pile.
A la sortie de la fonction, la zone de la pile occupée par les paramètres est libérée sans
sauvegarde des données. Les valeurs des paramètres redeviennent donc celles d'avant l'appel
de la fonction.
Les variables de la fonction appelante ne sont jamais modifiées au retour de la
fonction.

Si une fonction reçoit en argument la valeur d'une adresse, elle la stocke dans un
pointeur. Elle peut ensuite, en utilisant le contenu de l'objet pointé, modifier la variable dont
elle a reçu l'adresse.

La modification d'une variable par une fonction est réalisée en passant un


pointeur sur la variable.
Au retour de la fonction, le pointeur lui-même n'est pas altéré.

PS/LANGAGES Page 43
Les fonctions

7.4 Retour du résultat


Une fonction peut être porteuse d'un résultat après son exécution. Ceci sera fait grâce à
l'instruction return;
Cette instruction interrompt le déroulement de la fonction et exécute le retour au
programme appelant.
Si le type de la variable figurant dans return est différent de celui de la fonction , la
conversion est faite automatiquement.
On ne peut pas trouver de return dans une fonction de type void.
On peut trouver plusieurs return dans une fonction bien que ce soit contraire à la notion
de programme propre en programmation structurée.

7.5 Prototypes des fonctions


Placés en tête du programme (au minimum avant la première fonction), les prototypes
de fonctions sont facultatifs mais ont pour intérêt:
- de vérifier la validité (en quantité et qualité) des paramètres transmis aux fonctions.
- d'utiliser les fonctions dans n'importe quel ordre.
Le prototype d'une fonction est la déclaration de la fonction.

Il n'y a à l'exécution aucun contrôle ni sur le nombre ni sur le type des paramètres.
D'où l'intérêt d'utiliser un prototype systématique afin de détecter à la compilation les erreurs
non décelées à l'exécution.

PS/LANGAGES Page 44
Les fonctions

7.6 Exemples
Ecrire une fonction permettant de calculer le prix TTC en fonction du prix HT et de la
TVA.
1ère étape: la boite noire

f lo a t tv a
C a lc u l T V A f lo a t p r ix _ ttc
f lo a t p r ix _ h t

2ème étape : le prototype


float calcul_prix_ttc (float tva, float prix_ht);
ou
float calcul_prix_ttc (float, float);
Il n'est pas nécessaire d'indiquer au niveau du prototype le nom des arguments.
Notez le ; obligatoire dans la déclaration du prototype.

3ème étape : la définition de la fonction

float calcul_prix_ttc (float tva, float prix_ht)


{
float ttc;
ttc = (prix_ht * tva / 100) + prix_ht;
return (ttc);
}

Utilisation de cette fonction:


#include <stdio.h>
/* prototypes des fonctions utilisées par le programme */
float calcul_prix_ttc (float, float);
main()
{
float prix_achat, tauxtva, prixtotal;

puts ("Entrez le prix d'achat : ");


scanf ("%f", &prix_achat);
puts ("Entrez le taux de la TVA :");
scanf ("%f", &tauxtva);
prixtotal = calcul_prix_ttc(tauxtva, prix_achat);
printf("Le montant total est : %5.2f", prixtotal);
}

PS/LANGAGES Page 45
Les fonctions

void fonc(char );

main()
{
char c = 'a';
fonc(c);
putchar(c);
}

void fonc(char car)


{
putchar(car);
car = 'b';
putchar(car);
}

L'exécution de ce programme donne aba.


Explication:
Pile Pile Pile Pile

car a car b
c a c a c a c a

Allocation de la Appel de fonc, Exécution de car = 'b' Fin de la fonction


variable c de main allocation de car et C'est dans la pile qu'a Dépilement et retour
copie de la valeur de lieu la modification au main
c.
putchar(car) a putchar(car)b putchar(c)a

PS/LANGAGES Page 46
Les tableaux et les pointeurs

8. LES TABLEAUX ET LES POINTEURS


Un tableau est une suite d'éléments (suite d'emplacements mémoire) consécutifs de
même type.
Pour déclarer un tableau, il faut indiquer:
- son nom
- le type de ses éléments
- sa classe d'allocation mémoire
- sa dimension

Les indices commencent à zéro.


Les débordements ne sont pas gérés par le compilateur.
Le langage C dispose de pointeurs, c'est-à-dire de variables destinées à contenir des
adresses d'autres objets (variables, fonctions etc...).

A priori, ces deux notions de tableaux et de pointeurs paraissent éloignées. Mais il se


trouve qu'en C, un identificateur de tableau est une constante pointeur. Ce n'est pas une
lvalue.
Toute opération que l'on peut effectuer par indexation sur des tableaux peut être réalisée
à l'aide des pointeurs.

8.1 Les tableaux à un indice


Exemple : créer un tableau de 10 notes; calculer et afficher la moyenne

#include <stdio.h>
main()
{
int i, somme = 0;
float moyenne;
float note[10]; /* le tableau de notes de note[0] à note[9] */

for (i=0 ; i<10 ; i++)


{
printf("Donnez la note N°%d : ",i+1);
scanf("%f",&note[i]);
somme += note[i];
}
moyenne = somme / 10;
printf("la moyenne est de %5.2f",moyenne);
}
Remarque : la construction suivante est correcte:
#define MAX 10
...
int tab[MAX];

Par contre, elle ne serait pas correcte si on définissait N de la façon suivante:


const int N = 10;
car N n'est pas ici une expression constante. En effet, dans certaines conditions, selon
l'implémentation, N pourrait être modifié par une fonction qui recevrait un pointeur sur N.

8.1.1 Initialisation d'un tableau à un indice


La déclaration

PS/LANGAGES Page 47
Les tableaux et les pointeurs

int tab[5] = {10,20,30,40,50};


place les entiers 10,20,30,40,50 dans chacun des 5 éléments du tableau.
Il est obligatoire de mentionner les dimensions du tableau à la déclaration sauf s'il est
initialisé aussitôt.
Exemples: static char tabcart[] = {‘a’,’b’,’c’,'\0'}; /* ou */
static char tabcart[] = "abc"; /* idem */

Si le nombre d'initialisateurs est inférieur à la taille du tableau, les autres éléments sont
mis à zéro dans le cas des variables externes ou statiques, mais pour les variables
automatiques, ils prennent une valeur quelconque.

Il n'est pas possible d'initialiser un élément au milieu d'un tableau sans donner
également toutes les valeurs précédentes.
Exemple: static int tabent[10] = {2,3,4}; /* tableau de 10 entiers dont les 3 */
/* premiers ont pour valeur 2,3,4 */
/* les suivantes sont à 0 */

Un tableau déclaré static est initialisé par défaut à 0 ou à '\0'

8.2 Les tableaux multidimensionnels


En langage C, un tableau multidimensionnel est en fait un tableau à une seule
dimension dont chaque élément est un tableau (uni ou multidimensionnel).
Lorsque le compilateur rencontre une déclaration telle que
int tab[5][9];
il réserve un tableau de 45 (5 * 9) éléments. Un élément quelconque de ce tableau se
note tab[3][2] ou tab[i][j] ou tab[i+2][j-1].
Les éléments de ce tableau sont rangés en mémoire suivant l'ordre obtenu en faisant
varier le dernier indice en premier. Exemple pour le tableau tab

tab[0][0] tab[0][1] tab[0][2] ... tab[1][0] tab[1][1] tab[1][2] ... tab[2][0] ...

Cet ordre a une incidence dans plusieurs circonstances:


- lorsque l'on omet de préciser certaines dimensions du tableau
- lorsque l'on désire accéder à l'aide d'un pointeur aux différents éléments d'un tableau.
- lorsque l'un des indices déborde.

tab[1][1] est une lvalue alors que tab[1] n'en est pas une.
tab[1] est l'adresse du tableau tab[1] et est égal à &tab[1][0].

8.2.1 Initialisation d'un tableau multidimensionnel


int tab[3][4] = { {1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
ou plus simplement
int tab[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
La première forme consiste à considérer le tableau tab comme formé de 3 tableaux de 4
éléments. La seconde exploite la manière dont sont rangés les éléments en mémoire.

PS/LANGAGES Page 48
Les tableaux et les pointeurs

8.3 Les chaînes de caractères


Une chaîne de caractères est en fait un tableau particulier. Elle est donc déclarée de la
même manière.

char nom[10]; /* tableau de 10 caractères mais 9 caractères utiles */

Lors de l'initialisation de la chaîne de caractères, le système ajoute systématiquement un


marqueur de fin de chaîne ('\0'). La chaîne doit pouvoir contenir ce caractère. Une chaîne
déclarée de longueur n contiendra n-1 caractères utiles.

Si la chaîne n'est pas assez longue pour contenir le caractère ' \0 ' , ce dernier sera omis
et la chaîne ne pourra pas être utilisée comme telle.

Exemple:
main()
{
static char chaine[] = "bonjour";
/* ou static char chaine[8] = "bonjour"; */
printf("chaîne contient: %s\n",chaine);
}

On ne fait pas d'affectation de chaînes.


Exemple:
char nom[10];
nom = "bonjour"; /*Interdit car nom est une constante pointeur. On ne peut
pas la modifier.*/

8.3.1 Fonctions de traitement sur les chaînes de caractères


Les fonctions sur les chaînes, déclarées dans le fichier d'en-tête string.h ont des noms
qui commencent par str ou mem.
Dans l'ensemble de ces fonctions, aucun contrôle n'est effectué sur la longueur des
zones réceptrices. En cas de manque de place, les emplacements contigus sont écrasés.

8.3.1.1 strcpy (string.h)


char* strcpy(char *sl, const char *s2);
Copie la chaîne s2, y compris '\0' dans s1 et retourne l'adresse de s1 ou NULL si la
copie n'a pas pu se faire correctement.

8.3.1.2 strncpy (string.h)


char* strncpy(char *sl, const char *s2, size_t n);
Copie au plus n caractères de s2 dans s1 et retourne l'adresse de s1 ou NULL si la copie
n'a pas pu se faire correctement.
Complète par des '\0' si s2 comporte moins de n caractères.

PS/LANGAGES Page 49
Les tableaux et les pointeurs

8.3.1.3 strcat (string.h)


char* strcat(char *s1, const char *s2);
Concatène la chaîne s2 dans s1 et retourne l'adresse de la chaîne résultante (sl) ou
NULL si l'opération n'a pas pu se faire correctement.
Le caractère de fin de chaîne est copié automatiquement à la fin de la nouvelle chaîne
s1.
La concaténation s'effectue à partir du caractère de fin de chaîne de sl qui est effacé.

8.3.1.4 strncat (string.h)


char* strncat(char *s1, const char *s2, size_t n);
Concatène au plus n caractères de la chaîne s2 dans s1 et retourne l'adresse de la chaîne
résultante (sl) ou NULL si l'opération n'a pas pu se faire correctement.
Complète par des '\0' si s2 comporte moins de n caractères.

8.3.1.5 strcmp (string.h)


int strcmp(const char *sl, const char *s2);
Compare lexicographiquement deux chaînes dans l'ordre des caractères définis par le
code ASCII et renvoie un entier
< 0 si sl < s2.
= 0 si sl = s2.
> 0 si sl > s2.
La fonction effectue la comparaison à partir du premier caractère de chaque chaîne et
continue avec les caractères suivants jusqu’à ce que les caractères soient différents l'un de
l'autre ou que l'une des chaînes soit terminée.

8.3.1.6 strncmp (string.h)


int strncmp(const char *sl, const char *s2, size_t n);
Compare au plus n caractères de s1 à la chaîne s2 et renvoie un entier de la même façon
que strcmp.

8.3.1.7 strchr (string.h)


char *strchr(const char * s1, int c);
Retourne un pointeur sur la première occurrence de c dans s1, ou NULL si c ne figure
pas dans s1. c est un int converti en char.

8.3.1.8 strrchr (string.h)


char *strrchr(const char * s1, int c);
Retourne un pointeur sur la dernière occurrence de c dans s1, ou NULL si c ne figure
pas dans s1. c est un int converti en char.

8.3.1.9 strspn (string.h)


size_t strspn(const char *s1, const char *s2);
Retourne le nombre de caractères du début de s1 constitué de caractères appartenant à
s2.

PS/LANGAGES Page 50
Les tableaux et les pointeurs

8.3.1.10 strcspn (string.h)


size_t strcspn(const char *s1, const char *s2);
Retourne le nombre de caractères du début de s1 constitué de caractères n'appartenant
pas à s2.

8.3.1.11 strpbrk (string.h)


char * strpbrk(const char * s1, const char *s2);
Retourne un pointeur sur la première occurrence dans s1 de n'importe quel caractère de
s2, ou NULL si aucun n'y figure.

8.3.1.12 strstr (string.h)


char *strstr(const char *s1, const char *s2);
Retourne un pointeur sur la première occurrence de la chaîne s2 dans la chaîne s1, ou
NULL si elle n'y figure pas.

8.3.1.13 strlen (string.h)


size_t strlen(const char *s1);
Retourne la longueur de la chaîne s1, caractère nul non compris.

8.3.1.14 strerror (string.h)


char *strerror(size_t n);
Retourne un pointeur sur la chaîne correspondant à l'erreur n, définie par
l'implémentation.

8.3.1.15 strtok (string.h)


char *strtok(char *s1, const char *s2);
Recherche dans s1 des lexèmes délimités par des caractères appartenant à s2.

8.3.1.16 memcpy (string.h)


void *memcpy(void s1, const void s2, size_t n);
Copie n caractères de s2 dans s1 et retourne s1.

8.3.1.17 memmove (string.h)


void *memmove(char *s1, const char * s2, size_t n);
Comme memcpy mais fonctionne aussi si les objets se chevauchent.

8.3.1.18 memcmp (string.h)


int memcmp(const char *s1, const char *s2, size_t n);
Compare les n premiers caractères de s1 à s2. La valeur de retour se détermine comme
pour strcmp.

8.3.1.19 memchr (string.h)


void *memchr(const char *s1, int c, size_t n);
Retourne un pointeur sur la première occurrence du caractère c (int converti en
unsigned char) dans s1, ou NULL si c ne figure pas dans les n premiers caractères.

8.3.1.20 memset (string.h)


void *memset (char *s1, int c, size_t n);
Remplit les n premiers caractères de s1 par le caractère c et retourne s1.

PS/LANGAGES Page 51
Les tableaux et les pointeurs

8.4 Tableaux et Fonctions


Le nom du tableau représente en fait l'adresse du tableau . Si nous voulons modifier un
élément du tableau, il suffit de transmettre en paramètre le nom du tableau (éventuellement la
taille).
Exemple :
void init(int tablo[], int ind);
main()
{
int tab[10];
init(tab,10);
}
void init(int tablo[], int ind)
{
int i;
for (i = 0 ; i < ind ; i++)
tablo[i]=1;
}

Remarque : On aurait pu déclarer la fonction de la manière suivante:


void init(int tablo[10], int ind)
mais dans ce cas, la fonction init n'aurait pu travailler que sur un tableau de 10 entiers.

Lorsque l'on passe un tableau à plusieurs dimensions en argument à une fonction, le


nombre de lignes est sans importance car on passe en réalité son adresse. Par contre, la
fonction doit connaître les autres dimensions pour connaître l'organisation du tableau.

void ra_un(int t[][15], int nbl);


main()
{
int tablo[10][15];
ra_un (tablo, 10);
}
void ra_un(int t[][15], int nbl)
{ /* fonction permettant la mise à 1 de tableaux de 15 éléments */
int i, j;
for(i=0; i < nbl; i++)
for(j=0; j < 15; j++)
t[i][j] = 1;
}

PS/LANGAGES Page 52
Les tableaux et les pointeurs

8.5 Les pointeurs

8.5.1 Généralités
Un pointeur est une variable contenant l'adresse d'une autre variable ou d'une fonction.
Il est utilisé dans le passage de paramètres à une fonction (possibilité de modifier les
arguments pointés), la sauvegarde d'adresse ou pour le chaînage d'éléments.

Un pointeur peut pointer sur n'importe quel type de variable (y compris un autre
pointeur ou une fonction).

La taille d'un pointeur (taille d'un entier "mot machine" est la même quel que soit l'objet
pointé.)

8.5.2 Déclaration - Utilisation


<type> *<identificateur>;

<type> est le type de variable pointée.
* : indique qu'il s'agit d'un pointeur
Exemples:
int *ptr_int;
char *ptr_char;
int *ptr1, *ptr2, *ptr3;

int *adr;
int n;
n = 20; /* ins1 */
adr = &n; /* ins2 */
*adr = 30; /* ins3 */

L'instruction (ins2) adr = &n affecte à la variable pointeur adr l'adresse de n.


L'instruction (ins3) *adr = 30 signifie: affecter à la lvalue *adr la valeur 30. Or *adr
représente l'entier ayant pour adresse adr.

@ mémoire
2ff7fc10 n 20 n 20 n 30
2ff7fc14 adr adr 2ff7fc10 adr 2ff7fc10

ins1 ins2 ins3

Si l'on avait ajouté l'instruction


(*adr)++; le contenu de n serait devenu égal à 31.
Ne pas oublier les parenthèses (cf priorités et évaluation des opérateurs). C'est la lvalue
*adr que l'on incrémente.

PS/LANGAGES Page 53
Les tableaux et les pointeurs

8.5.3 Pointeurs constants et pointeurs de constantes


Soit la déclaration
const int *p;
On indique que l'on ne veut pas pouvoir modifier la valeur de l'objet pointé par p en
passant par le pointeur.
Exemple :
int strlen(const char * s1);

int *const p = &objet;


Ici p pointera toujours sur le même objet.
const int * const q = &objet;
q est un pointeur constant sur le même objet. Via p, on peut modifier l'objet pointé, via
q, on ne le peut pas.

Exemple :
int x = 10;
int *const p = &x;
const int * const q = &x;

*p = 20 ; /* OK */
*q = 30 ; /* Erreur de compilation *q n'est pas une lvalue*/

8.5.4 Arithmétique des pointeurs


Soit la déclaration
int *adr;
Une expression telle que adr + 1 a un sens pour le langage C. En effet, adr contient
l'adresse d'un entier donc adr + 1 représente l'adresse de l'entier suivant (en fait
incrémentation de sizeof(int)).
De la même façon,
adr++ ou adr-- incrémente ou décrémente l'adresse contenue dans adr.

Les opérations utilisables sur les pointeurs sont:

- l'addition ou la soustraction d'un pointeur et d'un entier.


- la comparaison entre pointeurs de même type.
- l'affectation de pointeurs de même type.
- la soustraction entre pointeurs de même type.

Toutes les autres opérations sont interdites.

L'affectation entre deux pointeurs de types différents nécessite un cast

8.5.5 L'allocation dynamique dans le tas


A côté des objets déclarés (statiques, automatiques, ...), il y a ceux alloués
dynamiquement dans une zone appelée tas (ou heap). On accède à ces objets obligatoirement
par des pointeurs.
Le tas est utilisé pour la construction de structures de données complexes dont on ne
connaît pas à priori la taille.
Le langage C comporte des fonctions (prototypes dans stdlib.h) pour allouer ou
désallouer de la mémoire.

PS/LANGAGES Page 54
Les tableaux et les pointeurs

8.5.5.1 malloc (stdlib.h)


void *malloc(size_t size);
malloc retourne un pointeur sur un espace mémoire reservé à un objet de taille size, ou
bien NULL si cette demande ne peut être satisfaite. La mémoire allouée n'est pas initialisée.

8.5.5.2 calloc (stdlib.h)


void *calloc(size_t nobj, size_t size);
calloc retourne un pointeur sur un espace mémoire réservé à un tableau de nobj objets,
tous de taille size, ou bien NULL si cette demande ne peut être satisfaite. La mémoire allouée
est initialisée par des zéros.

8.5.5.3 realloc (stdlib.h)


void *realloc(void *p, size_t size);
realloc change en size la taille de l'objet pointé par p. Si la nouvelle taille est plus petite
que l'ancienne, seul le début du contenu de l'objet est conservé. Si la nouvelle taille est plus
grande que l'ancienne, le contenu de l'objet est conservé.

8.5.5.4 free (stdlib.h)


void free(void *p);
free libère l'espace mémoire pointé par p; elle ne fait rien si p vaut NULL. p doit être un
pointeur sur un espace mémoire alloué par une des fonctions précédentes. p n'est pas modifié.

8.5.6 Les pointeurs génériques


Les fonctions calloc et malloc sont deux exemples de fonction retournant un pointeur
générique (du type void *).
Exemple:
void demi(void *pt, char type);
main()
{
int i=5;
float x=15.4;
demi(&i, 'i');
printf("%d\n", i);
demi(&x, 'f');
printf("%f\n", x);
return 0;
}
void demi(void *pt, char type)
{ switch(type)
{ case 'i' : *(int*)pt /= 2;break;
case 'l' : *(long*)pt /=2;break;
case 'f : *(float *)pt /=2.;break;
}
}
Remarque : il est nécessaire d'effectuer un transtypage.

PS/LANGAGES Page 55
Les tableaux et les pointeurs

8.5.7 Les pointeurs de fonction


Une fonction elle-même n'est pas une variable, mais il est possible de définir des
pointeurs de fonctions que l'on peut affecter, placer dans des tableaux, passer en arguments à
des fonctions, etc... La déclaration suivante est une déclaration de pointeur de fonction qui
renvoie un entier et qui admet deux entiers comme paramètre.

int (*pointeur_fonc)(int, int);

Attention à l'utilisation des parenthèses. La déclaration suivante correspond à une


fonction qui retourne un pointeur sur un entier.
int * pointeur2(int, int);

Exemple:
int plus (int a, int b);
int moins (int a, int b);
int operation (int a, int b, int (*ope)(int, int));
main()
{
int i = 10, j = 5;
printf("La somme de %d et %d est %d\n", operation(a, b, plus));
printf("La différence de %d et %d est %d\n", operation(a, b, moins));
}
int plus (int a, int b)
{ return a + b;
}
int moins (int a, int b)
{ return a - b;
}
int operation (int a, int b, int (*ope)(int, int))
{ return ope(a,b);
}

8.5.8 Les pointeurs et les arguments de fonction


Comme déjà signalé dans le chapitre 7 (Les fonctions), les arguments à une fonction
sont passés par valeur. Ainsi le programme suivant réalise l'échange des copies des
arguments dans la pile.
#include <stdio.h>
void echange(int a, int b);
main()
{ int i = 15, j = 25;
printf("Valeurs de i = %d et de j = %d avant echange\n", i, j);
echange(i, j);
printf("Valeurs de i = %d et de j = %d après echange\n", i, j);
}
void echange(int a, int b)
{ int tampon ;
tampon = a;
a = b;
b = tampon;
}
Exécution
Valeurs de i = 15 et de j = 25 avant echange

PS/LANGAGES Page 56
Les tableaux et les pointeurs

Valeurs de i = 15 et de j = 25 après echange


En effet

@ mémoire
2ff7fc00 i 15 i 15 i 15 i 15
2ff7fc04 j 25 j 25 j 25 j 25

2ff7fbe0 a 15 a 25
2ff7fbe4 b 25 b 15
2ff7fbc0 tampon tampon 15
Début du Début de Fin de Fin du
main echange echange main

Modifions maintenant le programme de la façon suivante:

#include <stdio.h>
void echange(int *pa, int *pb);
main()
{ int i = 15, j = 25;
printf("Valeurs de i = %d et de j = %d avant echange\n", i, j);
echange(&i, &j);
printf("Valeurs de i = %d et de j = %d après echange\n", i, j);
}
void echange(int *pa, int *pb)
{ int tampon ;
tampon = *pa;
*pa = *pb;
*pb = tampon;
}
Exécution
Valeurs de i = 15 et de j = 25 avant echange
Valeurs de i = 25 et de j = 15 après echange

@ mémoire
2ff7fc00 i 15 i 15 i 25 i 25
2ff7fc04 j 25 j 25 j 15 j 15

2ff7fbe0 pa 2ff7fc00 pa 2ff7fc00


2ff7fbe4 pb 2ff7fc04 pb 2ff7fc04
2ff7fbc0 tampon tampon 15
Début du Début de Fin de Fin du
main echange echange main

PS/LANGAGES Page 57
Les tableaux et les pointeurs

8.5.9 Les pointeurs et les opérations sur les tableaux


main()
{ int t[10] = {5,3,2,7,9,8,6,4,1,7};
int *pt = t;
int i, j;

i = *pt /* donc i = 5 valeur pointée par pt */


j = *(pt + 1); /* j = 3 valeur pointée par le suivant de pt */
pt + 1 est donc l'adresse de l'élément t[1].
De la même façon:
(pt + i) est l'adresse de t[i], donc
(pt + i) est donc le même objet que t[i]

Les notations suivantes sont équivalentes


t[i]
*(t + i) L'opérateur + est commutatif
*(i + t)
i[t] L'opérateur [] est commutatif

Dans le cas de tableaux multidimensionnels


main()
{ int t[3][3] = { {1,3,5},
{2,4,6},
{7,8,9}};
int *p; /* p est un pointeur sur un entier */
int *ptr[3]; /* ptr est un tableau de pointeurs */
int (*pm)[3]; /* pm est un pointeur sur un tableau de 3 entiers */

p=t; /* ERREUR car p est un pointeur sur un entier */


/* et t est un pointeur sur un tableau de 3 entiers */

p = &t[0][0]; /* CORRECT */
ptr[0] = p + 1;
printf("%d\n", *(ptr[0])); /* affiche la valeur 3 */
ptr[1] = &t[0][2];
printf("%d\n", *(ptr[1])); /* affiche la valeur 5 */
pm = t /* CORRECT */
printf("%d\n", *(pm[0])); /* affiche la valeur 1 */
}

Un tableau à 2 dimensions est l'équivalent d'un pointeur sur les lignes de ce tableau. Si
on augmente de 1 un tel pointeur, on doit se décaler de la "largeur" d'une ligne (en fait le
nombre de colonnes du tableau).

Les notations suivantes sont équivalentes


t[i][j]
*(*(t + i)+j) L'opérateur + est commutatif
*(j + *(t + i))
j[i[t]] L'opérateur [] est commutatif

PS/LANGAGES Page 58
Les tableaux et les pointeurs

8.5.10 Les pointeurs et les chaînes de caractères


La déclaration
char *message;
déclare un pointeur sur un caractère mais ne reserve pas de place en mémoire.
char *message = "bonjour";
déclare un pointeur sur un caractère qui est initialisé sur la chaîne "bonjour\0".

message  b o n j o u r \0

Les déclarations suivantes ne sont pas identiques:


char message1[] = "bonjour";
char *message2 = "bonjour";
Dans le premier cas, il n'y a qu'un tableau de 8 caractères alors que dans le deuxième
cas, il y a un pointeur et un tableau de 8 caractères.

8.5.11 Les tableaux de pointeurs


La déclaration
char *lignes[7];
déclare un tableau de 7 pointeurs sur un caractère.

La déclaration
char *mois[12] = {
"janvier","février","mars","avril","mai","juin",
"juillet","août","septembre","octobre","novembre","décembre"};
déclare et initialise un tableau de pointeurs sur les chaînes de caractères.

mois
0  j a n v i e r \0
1  f é v r i e r \0
2  m a r s \0
3  a v r i l \0
4  m a i \0
5  j u i n \0
6  j u i l l e t \0
7  a o û t \0
8  s e p t e m b r e \0
9  o c t o b r e \0
10  n o v e m b r e \0
11  d é c e m b r e \0

On peut remarquer que la place mémoire est adaptée au contenu des données. Ce qui ne
serait pas le cas si on avait utilisé la déclaration suivante:
char mois[12][10] = {
{"janvier"},{"février"},{"mars"},{"avril"},{"mai"},{"juin"},
{"juillet"},{"août"},{"septembre"},{"octobre"},{"novembre"},{"décembre"}};

PS/LANGAGES Page 59
Les tableaux et les pointeurs

8.5.12 Les paramètres du programme principal


Il s'agit en fait d'un exemple d'utilisation des tableaux de pointeurs sur tableaux.
Le programme principal peut recevoir des paramètres qui apparaîtront sur la ligne de
commande après le nom du fichier exécutable.
Les paramètres possibles sont:
- argc un entier (argument count) signifiant nombre d'arguments.
- argv un pointeur sur un tableau de chaînes de caractères (argument
vector)

Exemple d'utilisation :
Ligne de commande : program bonjour, maître
Par convention, argv[0] est le nom par lequel le programme a été appelé (ici program)
et par conséquent argc vaut au moins 1.
argv
  program\0
 bonjour,\0
 maître\0
0

Le programme suivant affiche de deux manières différentes les arguments passés à


program.
#include <stdio.h>
main(int argc, char *argv[])
{
int i;

for (i=1 ; i < argc; i++)


printf("%s%s", argv[i], (i < argc - 1) ? " " : "");
putchar('\n');
/* ou encore */
while ( --argc > 0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
putchar('\n');
}

PS/LANGAGES Page 60
Les types énumérés et structures

9. LES TYPES ENUMERES ET STRUCTURES

9.1 Les énumérations


Une énumération est une liste de valeurs entières constantes que l'on appelle des
énumérateurs..

enum [<identificateur>] {<liste des constantes>}.

La liste des constantes est une suite d'identificateurs séparés par des virgules.

Des valeurs sont automatiquement associées aux identificateurs dans un ordre croissant
au pas de 1.
Si aucune initialisation particulière n'est effectuée, le premier identificateur est associé à
0, le second à 1 et ainsi de suite.
Les valeurs associées aux identificateurs ne sont pas modifiables dans le code des
programmes.

Exemples :
enum liste {zero, un, deux, quatre = 4, cinq};
enum liste var = zero;
printf("%d",var); /* résultat: 0 */

typedef enum {FAUX,VRAI} booleen;


booleen choix;
int a, b;
scanf("%d %d", &a, &b);
choix = (a > b);
if (choix == FAUX)
printf("%d est < ou = à %d\n", a, b);
else
printf("%d est supérieur à %d\n", a, b);

PS/LANGAGES Page 61
Les types énumérés et structures

9.2 Les structures

9.2.1 Généralités - Déclaration


Une structure est une collection de données regroupées dans une même entité logique.
Elles permettent de créer des types complexes à partir de différents types déja connus et de
les regrouper sous un même nom.

Les seules opérations permises sur les structures sont:


- la copie
- l'affectation
- l'accès à ses membres
- la récupération de son adresse.

Par contre, les membres d'une structure sont utilisés comme n'importe quelle autre
variable.
Pas de comparaisons entre structures en raison de l'alignement des données et de la
possibilité de présence de bits de bourrage.

struct [<nom struct> ]


{
typel <nom élémentl>, <nom élément2>;
type2 <nom élément3>;
} [<varl>, <var2> ... ];

Exemple :

struct enreg
{
int numero, qte;
float prix;
};

Cette déclaration définit un modèle de structure mais ne réserve pas de variable


correspondant à cette structure. Une fois le modèle défini, nous pouvons déclarer des
variables du type correspondant.
Exemple:
struct enreg article;

Dans cette déclaration, on réserve un emplacement mémoire de la taille d'une structure


de type enreg.

Il est possible de regrouper la définition du modèle et la déclaration de la variable dans


une seule instruction. Ainsi, l'opération précédente aurait pu s'écrire:
struct enreg
{
int numero, qte;
float prix;
} article;

Dans ce dernier cas, il est possible d'omettre le nom du modèle (enreg) à condition de
ne pas avoir à déclarer par la suite d'autres variables du même modèle.

PS/LANGAGES Page 62
Les types énumérés et structures

struct adr
{ int numero;
char rue[30];
long codepostal;
char ville[15];
};
struct compte
{ long numero;
char nom[15];
char prenom[10];
struct adr adresse;
} compte1;

struct compte compte2;


}

compte1 et compte2 sont deux variables de type struct compte.

Restriction : un champ ne peut pas être de type fonction.

typedef struct
{ int jour, mois, annee;
} date;

/* date est ici un alias de type, et non pas un vrai type personnalisé comme auparavant
*/

date date_naissance;

9.2.2 Initialisation des structures


1) struct famille{
char nom[15];
char prenom[10];
int nb_enfants;
} famille1 = {"DUPONT","Jean",3};

2) struct famille famille2 = famille1;

3) struct famille famille3 = {"DURAND","Pierre",4};

9.2.3 Accès aux éléments


<identificateur de la variable>.<nom du champ>

struct famille famille4;


strcpy(famille4.nom , "DUPUIS");
strcpy(famille4.prenom, "Eric");
famille4.nb_enfants = 0;

9.2.4 Structures et Fonctions


Une structure peut être passée en argument à une fonction et une fonction peut
retourner une structure.

PS/LANGAGES Page 63
Les types énumérés et structures

La structure étant considérée comme un tout, elle est passée en paramètre comme
n'importe quel autre type de variable.

Exemple :
struct date
{ int jour, mois,annee;
};

struct personne
{ char nom[20], prenom[15];
struct date date_naiss;
};

/* fonction retournant une structure de type personne */


struct personne maj_pers(char name[],char pren[], struct date d_naiss)
{
struct personne tempo;
tempo.date_naiss = d_naiss;
strcpy(tempo.nom,name);
strcpy(tempo.prenom, pren);
return tempo;
}

main()
{
static struct date datel = {10,07,97};
struct personne persl;

persl = maj_pers("TOTO","Jean",datel);
printf("%s %s %d/%d/%d",persl.nom,pers1.prenom,
persl.dat_naiss.jour, pers1.date_naiss.mois, pers1.date_naiss.annee);
}

PS/LANGAGES Page 64
Les types énumérés et structures

9.2.5 Pointeurs sur une structure


struct famille{
char nom[15];
char prenom[10];
int nb_enfants;
} famille5;

struct famille *pt;

pt = &famille5;


Contrairement aux tableaux et aux chaînes de caractères, le nom d'une variable
structure n'est pas assimilé à un pointeur constant (adresse).
Il faut toujours utiliser l'opérateur & pour désigner l'adresse d'une structure.

Pour accéder à un champ d'une structure pointée par pt:


strcpy((*pt).nom , "MARTIN");
ou
strcpy(pt->nom, "MARTIN");


Attention aux priorités
L'opérateur -> a une priorité supérieure à l'opérateur ++
Exemples
++pt->nb_enfants; /* Incrémentation du champ nb_enfants */
(++pt)->nb_enfants; /* Incrémentation du pointeur */

9.2.6 Structures récursives


Si le nombre d'objets (structures) n'est pas connu, une solution consiste à utiliser une
construction plus complexe qu'un tableau mais assez souple appelée liste. Dans le cas d'une
liste linéaire, la cellule contient de plus l'adresse (un pointeur sur) de la cellule suivante.
Dans une structure récursive, un (ou plusieurs membres) fait référence à la structure
même alors qu'elle n'est pas définie dans sa totalité.

La construction est la suivante:


struct cellule
{ int valeur;
struct cellule *suivant;
};

struct cellule *pt, *tete;


tete

10 15 12

NULL

Ainsi, connaissant la valeur de tete, on peut parcourir la liste du début à la fin. La fin est
signalée par la valeur du champ suivant qui est égale à NULL.

PS/LANGAGES Page 65
Les types énumérés et structures

9.3 Les unions


L'union permet de déclarer des objets polymorphes : objets qui peuvent changer de
forme mais qui n'ont à un moment donné qu'une forme et une seule.
L'union permet de faire partager un même emplacement mémoire par des variables de
types différents. Elle permet :
- d'économiser des emplacements mémoire.
- d'interpréter de façons différentes un même motif binaire

Lors de la déclaration de la variable, la structure de données ne réserve en mémoire que


la place nécessaire au stockage de la plus grande des entités qu'elle contient.

union [nom]
{
typel varl;
type2 var2;
} var;

Exemples:
main()
{
union essai
{
long n;
float x;
}union1;

printf("donner un nombre réel : ");


scanf("%f",&union1.x);
printf("en entier celà fait : %ld",union1.n);
}

Exécution :
donner un nombre réel : 1.23e4
en entier celà fait : 1178611712

union donnee
{ char nom[10];
int numero;
float reel;
}u1;

u1 a 3 formes possibles:
- un tableau de 10 caractères
- un entier
- un float

Rappel : en C, pas de contrôle d'accès aux champs.

PS/LANGAGES Page 66
Les types énumérés et structures

u1.numero = 256;
printf("%x--%x--%x--%x\n", u1.nom[0], u1.nom[1], u1.nom[2], u1.nom[3]);
u1.numero = 257;
printf("%x--%x--%x--%x\n", u1.nom[0], u1.nom[1], u1.nom[2], u1.nom[3]);
u1.numero = 278;
printf("%x--%x--%x--%x\n", u1.nom[0], u1.nom[1], u1.nom[2], u1.nom[3]);

Exécution:
0--0--1--0
0--0--1--1
0--0--1--16

 Attention, ces résultats sont valables sous UNIX. Dans le cas de processeur INTEL,
avec le même programme, on obtiendrait un résultat différent du fait de l'inversion des octets.
Sous TURBO C:
0--1--0--0
1--1--0--0
16--1--0--0

Autre exemple:
typedef enum {cartesien, polaire} representation;
typedef struct
{ float reel, imaginaire } rep_cartesien;
typedef struc
{ float rho, theta} rep_polaire;
typedef struct
{ representation rep;
union
{ rep_cartesien champ_cart;
rep_polaire champ_pol;
} info;
} complexe;

complexe c;

c.representation = polaire;
c.info.champ_pol.rho = 10;
Le champ rep sert de discriminant.

9.4 Les champs de bits


Il est possible d'indiquer comment les champs d'une structure seront représentés. Le
nombre constant indique la longueur du champ de bits.
typedef struct{
unsigned int code : 7; /* les 7 premiers bits */
unsigned int : 1; /* 1 bit inutilisé */
unsigned int reg1 : 4;
unsigned int reg2 : 4;
} format;

Les champs de bits n'ont pas d'adresse donc pas de pointeur sur ces champs.

PS/LANGAGES Page 67
Les types énumérés et structures

9.5 typedef
La directive typedef est employée pour définir un nouveau type à partir des types
existants. Les types ne sont pas réellement créés, mais les noms définis sont synonymes d'un
type existant qui pourrait être utilisé à leur place. Dans des cas simples, le typedef joue le rôle
similaire que la directive de compilation #define. Mais typedef permet de résoudre des cas qui
ne peuvent être traités par le #define (ou lorsque la directive de compilation échoue).

L'utilisation de typedef permet de rendre des programmes plus facilement portables. La


définition et la modification de type ne devra être faite que dans un seul fichier.

Il autorise également une lecture ou une documentation du code plus aisée en rendant
les noms de types plus explicites.

Syntaxe:
typedef type identificateur;
type: n'importe quel type de données déjà existant.
identificateur: l'identificateur en C, il peut être utilisé comme synonyme de type.

Remarques:
- Les modificateurs de type (short, long, signed, unsigned) ne peuvent être
utilisés sur des types définis par un typedef, même si ceux-ci sont synonymes d'un
type qui les admet.

typedef int entier;


✭ unsigned entier nombre; /* déclaration illégale */

- Plusieurs synonymes d'un type peuvent être définis dans un même typedef,
ceux-ci sont alors séparés par des virgules.

- L'instruction typedef permet de définir n'importe quel type, y compris les


types pointeurs, fonctions et tableaux.
Exemples:

typedef enum {FAUX,VRAI} booleen;


typedef char chaine[128], *pointeur_char, fonction_char();
typedef int (* pointeur_sur_fonction)();

booleen trouve=FAUX;
chaine ch1, ch2;
pointeur_char pt_ch;
pt_ch = &ch1[127];
pointeur_sur_fonction fonction_quitter;

✭Attention à l'abus des typedef qui peut rendre un code difficilement


compréhensible et donc produire l'effet contraire de celui escompté.

PS/LANGAGES Page 68
Les fichiers

10. LES FICHIERS

10.1 Généralités
Le langage C reconnaît un fichier comme une suite séquentielle d'octets. Le
déplacement dans ce fichier se fait à l'aide d'un pointeur. La gestion des entrées-sorties est
décrite dans stdio.h .

Le nombre maximum de fichiers pouvant être ouverts simultanément et la taille de la


mémoire tampon allouée pour chacun d'eux sont définis dans stdio.h (FOPEN_MAX et
BUFSIZ).

En C, tous les fichiers sont considérés comme un ensemble amorphe d'octets. Il n'y a
pas de notion de fichiers typés.


Sous DOS, il existe deux types de fichiers:
fichier binaire copie des octets
fichier texte copie des octets avec interprétation des caractères spéciaux
<Retour chariot> et <Nouvelle ligne>

Sous UNIX, uniquement des fichiers binaires. Pour favoriser la portabilité, TURBO C
propose une variable _fmode définie dans <stdlib.h> qui peut prendre l'une des deux valeurs
suivantes: O_BINARY ou O_TEXT qui sont définies dans <fcntl.h>. On peut également
ajouter b dans le mode d'ouverture pour spécifier un fichier binaire (ou t pour un fichier texte
par défaut).

10.2 Les fonctions de gestion de fichier


Il existe deux classes de fonctions permettant de gérer les fichiers.
• Les fonctions de niveau 1 ("LOW LEVEL") ont les caractéristiques suivantes:
-Elles sont proches et donc dépendantes du système d'exploitation.
-Les fichiers sont identifiés par un simple numéro.
-Les informations sont manipulées en binaire et n'offrent pas de possibilité de
formatage.

• Les fonctions de niveau 2 ("STREAM") ont les caractéristiques suivantes:


-Elles font appel aux fonctions de niveau 1.
-Les fichiers peuvent être manipulés soit en binaire soit faire l'objet de formatage.
-Les fichiers sont identifiés par un pointeur de type FILE. Ce type désigne un
modèle de structure défini dans <stdio.h> et sera utilisé lors de chaque
manipulation du fichier.

Ces fonctions utilisent ou mettent à jour des variables globales décrites dans des fichiers
d'en-tête.

La gestion des erreurs nécessite l'inclusion du fichier <errno.h> . La principale variable


utilisée est errno :
Quand une erreur survient lors d'un appel système la variable errno prend une valeur
indiquant le type d'erreur.
Cette variable peut être consultée à tout moment grâce à la fonction perror().

PS/LANGAGES Page 69
Les fichiers

10.3 Les fonctions de niveau 1

10.3.1 open (fcntl.h)


Ouvre un fichier.
int open (char * chemin, int omode, [int amode]);
Renvoie un handle désignant le fichier pour les opérations ultérieures.

L'argument omode définit le mode d'ouverture.


mnémonique opération
O_APPEND Ecriture à partir de la fin du fichier
O_BINARY Ouverture en mode binaire (DOS)
O_CREAT Si le fichier n'existe pas, il est créé
O_NDELAY Ne se bloque pas si l'ouverture nécessite un délai
O_RDONLY Ouverture en lecture seule
O_RDWR Ouverture en lecture et écriture
O_TEXT Ouverture en mode texte (DOS)
O_TRUNC Ouvre un fichier déjà existant en réduisant sa taille à 0. Le fichier
doit posséder des droits d'écriture
O_WRONLY Ouvre en écriture seule

Plusieurs paramètres omode peuvent être spécifiés, ils sont alors séparés par le
caractère '|'. Certains paramètres sont exclusifs les uns des autres (Exemple O_TEXT et
O_BINARY).

L'argument amode n'est utilisé que si l'option O_CREAT a été invoquée. Il correspond
sous UNIX aux valeurs utilisées par chmod (valeurs comprises entre 0000 et 0777).

Sous DOS, l'argument amode peut prendre les valeurs suivantes:


mnémonique opération
S_IWRITE Ecriture seule
S_IREAD Lecture seule
S_IREAD | S_IWRITE Lecture et écriture autorisées

10.3.2 eof (fcntl.h)


Détermine si le pointeur de fichier associé au handle a atteint la fin du fichier.
int eof (int handle);
Renvoie 1 si la fin de fichier est détectée et 0 sinon.

PS/LANGAGES Page 70
Les fichiers

10.3.3 read
Lecture dans un fichier.
int read (int handle, void * buffer, unsigned nb);
Lit dans un fichier référencé par handle, nb octets qui sont stockés dans le tampon
buffer.
La lecture commence à la position courante du pointeur de fichier dans le fichier.

Sous DOS, si le fichier est ouvert en mode texte, la séquence CR-LF est remplacée par
un caractère newline et le caractère CTRL-Z (^Z) est interprété comme caractère de fin de
fichier.

La fonction renvoie:
⇒ le nombre d'octets réellement lus.
⇒ 0 en cas de détection de fin de fichier
⇒ -1 en cas d'erreur (errno prend la valeur EBADF ou EACCES).

10.3.4 write
Ecriture dans un fichier
int write (int handle, void * buffer, unsigned nb);
Ecrit nb octets pris dans buffer dans le fichier référencé par handle.
L'écriture commence à la position courante dans le fichier.
Sous DOS, si le fichier est ouvert en mode texte, le caractère newline est remplacé par
la séquence CR-LF et un caractère CTRL-Z (^Z) est ajouté en fin de fichier.

La fonction renvoie:
⇒ le nombre d'octets réellement écrits.
⇒ -1 en cas d'erreur (errno prend la valeur EBADF ou EACCES).

10.3.5 close (fcntl.h)


int close (int handle);
Ferme le fichier désigné par handle.
Les tampons système associés sont vidés.
La fonction renvoie:
⇒ 0 en cas de succès
⇒ -1 en cas d'erreur (errno prend la valeur EBADF)

10.3.6 lseek (fcntl.h)


Attention, cette fonction n'est pas dans la norme ANSI.
long lseek (int handle, long depl, int orig);
Déplace le pointeur de fichier de depl octets à partir de orig.

Orig peut prendre les valeurs suivantes:


0 SEEK_SET depuis le début de fichier.
1 SEEK_CUR depuis la position courante du pointeur
2 SEEK_END depuis la fin de fichier

PS/LANGAGES Page 71
Les fichiers

10.4 Les fonctions de niveau 2

10.4.1 fopen (stdio.h)


Ouvre un fichier.
FILE* fopen(char *nomfic,char *mode);
La fonction retourne un pointeur sur le fichier en cas de réussite sinon NULL.

Les différents modes d'accès sont en écriture (w, w+), en lecture (r, r+) ou en
ajout(a, a+). Il peut être exprimé soit sous la forme d'une variable soit sous la forme d'une
constante.

Mode d’accès w r a
Fichier
N’existe pas Crée le fichier Erreur Crée le fichier
Ouvre en écriture Ouvre en écriture
Existe Détruit l’ancien Ouvre en lecture Ouvre en ajout en
Crée le fichier fin de fichier
Ouvre en écriture

Mode d’accés w+ r+ a+
Fichier Mise à jour
N’existe pas Crée le fichier Erreur Crée le fichier
Ouvre en E/S Ouvre en E/S
Existe Détruit l’ancien Ouvre en E/S Ouvre en E/S
Crée le fichier en fin de fichier
Ouvre en E/S

w+ création pour mise à jour


r+ mise à jour en lecture/écriture. Le fichier doit exister.
Il n'est pas possible de réaliser une lecture après une écriture (et vice-versa)
sans se repositionner (par un fseek ou autre).
Il est possible d'enchaîner plusieurs lectures (ou écritures) consécutives.
a+ extension et mise à jour. L'écriture n'est possible qu'en fin de fichier.

Sous DOS, il est possible d'ajouter b (pour binaire) ou t (pour texte).


Exemple :
ptr_fic = fopen ("ESSAI.DAT", "wb+");

10.4.2 fclose (stdio.h)


Ferme un fichier et force l'écriture sur disque du contenu du tampon associé au flux.
int fclose (FILE *ptr_fic);
La fonction retourne 0 si la fermeture s'est bien passée ou EOF dans le cas contraire.

PS/LANGAGES Page 72
Les fichiers

10.4.3 fseek (stdio.h)


Positionne le pointeur de fichier.
int fseek(FILE *ptr_fic, long int depl, int orig);

depl : Taille du déplacement en octets (+ ou - )


orig : Origine du déplacement

Orig peut prendre les valeurs suivantes:


0 SEEK_SET depuis le début de fichier.
1 SEEK_CUR depuis la position courante du pointeur
2 SEEK_END depuis la fin de fichier

SEEK_SET, SEEK_END et SEEK_END sont définies dans <stdio.h>.

La fonction retourne 0 si le déplacement a pu se faire ou différent de 0 dans le cas


contraire.

Cette fonction permet de gérer les fichiers en accès direct, le déplacement du pointeur
étant géré par l'utilisateur qui doit connaître la position dans le fichier de la donnée
recherchée.

10.4.4 rewind (stdio.h)


Positionne le pointeur en début de fichier.
void rewind(FILE *ptr_fic,);
Idem fseek (ptr_fic, 0L, 0);

10.4.5 ftell (stdio.h)


Retourne la position courante du pointeur d'un fichier.
long int ftell (FILE *ptr_fic);
La fonction retourne la position courante ou EOF s'il y a une erreur.
La position courante du pointeur est le déplacement en octets par rapport au début du
fichier.

10.4.6 feof (stdio.h)


Détecte une fin de fichier.
int feof (FILE *ptr_fic);
La fonction retourne une valeur non nulle (vraie) si l'indicateur de fin de fichier a été
détecté lors de la dernière opération de lecture.

Il est nécessaire d'avoir tenté de lire au delà de la fin de fichier pour que la fonction
renvoie un résultat non nul.

PS/LANGAGES Page 73
Les fichiers

10.4.7 ferror (stdio.h)


Détecte les erreurs.
int ferror(FILE *ptr_fic);
La fonction retourne une valeur non nulle (vraie) lorsqu'une erreur est détectée.

La fonction teste la possibilité de lire ou d'écrire dans un fichier et met à jour la variable
errno.

10.4.8 clearerr (stdio.h)


Réinitialise l'indicateur d'erreur.
void clearerr (FILE *ptr_fic);
La fonction réinitialise les indicateurs d'erreurs et de fin de fichier.

10.4.9 perror (stdio.h)


Affiche les messages d'erreurs systèmes.
void perror(char *s);
La fonction affiche dans un premier temps le message 's' suivi de deux points puis le
message correspondant à la dernière erreur système.

10.4.10 getw (stdio.h)


Lit un entier (un mot machine) dans un flux.
int getw(FILE *ptr_fic);
En cas de réussite, la fonction renvoie l'entier suivant dans le fichier d'entrée . En cas
d'erreur (fin de fichier ... ) la fonction renvoie EOF (-1 ).

EOF étant un entier autorisé, il est nécessaire de recourir à la fonction ferror( ) pour
tester la réussite de getw( ).

10.4.11 putw (stdio.h)


Ecrit un entier (un mot machine) dans un flux.
int putw(int var,FILE *ptr_fic);
La fonction renvoie l'entier écrit en cas de réussite. En cas d'erreur (fin de fichier ...) la
fonction renvoie EOF (-l).
EOF étant un entier autorisé, il est nécessaire de recourir à la fonction ferror( ) pour
tester la réussite de putw( ).

10.4.12 fflush (stdio.h)


int fflush(FILE *stream);
Sur un flot de sortie, fflush provoque l'écriture des données mises en mémoire tampon.
Sur un flot d'entrée, son effet est indéfini. Elle retourne EOF lors d'une erreur, zéro sinon.

PS/LANGAGES Page 74
Les fichiers

10.4.13 fwrite (stdio.h)


Ecrit des données dans un fichier, à partir de la position courante du pointeur dans le
fichier ( sauf en mode ajout).
size_t fwrite(void *donnee, size_t taille, size_t n, FILE *ptr_fic);

void *donnee : Adresse de la donnée à écrire.


size_t taille : Taille en octets de la donnée à écrire.
size_t n : Nombre de données à écrire (si n > 1 c'est le nombre
total d'octets transférés = n x taille ).

La fonction retourne le nombre de données écrites ( si ce nombre est différent de n,


alors une erreur s'est produite lors de l'écriture

10.4.14 fread (stdio.h)


Lit des données depuis un fichier, à partir de la position courante du pointeur dans le
fichier.
size_t fread(void * donnee, size_t taille, size_t n, FILE *ptr-fic);

void *donnee : Adresse où sera stockée la donnée.


size_t taille : Taille en octets de la donnée à lire.
size_t n : Nombre de données à lire (si n > 1 c'est le nombre total
d'octets transférés = n x taille )

La fonction retourne le nombre de données lues ( si ce nombre est différent de n, alors


une erreur s'est produite lors de la lecture).

10.4.15 Autres fonctions de lecture-écriture


On peut également utiliser les fonctions standards d'entrées-sorties décrites dans le
chapitre 5 (Les entrées-sorties sur les voies standards) telles que fputc, fgetc, fscanf, fprintf,
fgets, fputs.

10.4.16 Autres opérations sur les fichiers


FILE *freopen(const char *filename, const char *mode, FILE *stream);
freopen ouvre le fichier et lui associe un flot. Elle retourne un flot, ou NULL en cas
d'erreur. S'utilise pour changer les fichiers associés à stdin, stdout ou stderr.

int remove(const char *filename);


remove détruit le fichier. Retourne une valeur différente de zéro en cas d'échec.

int rename(const char *oldname, const char *newname);


rename change le nom du fichier oldname en newname. Retourne une valeur différente
de zéro en cas d'échec.

FILE *tmpfile(void);
tmpfile crée un fichier temporaire dans le mode "wb+" qui sera automatiquement détruit
lors de sa fermeture ou lors de la fin normale du programme. tmpfile retourne un flot ou
NULL si le fichier ne peut pas être créé.

char *tmpnam(char s[L_tmpnam]);

PS/LANGAGES Page 75
Les fichiers

tmpnam(NULL) crée une chaîne de caractères qui n'est pas le nom d'un fichier existant
et retourne un pointeur sur un tableau statique interne. tmpnam(s) stocke cette chaîne dans s et
renvoie s. tmpnam génère un nom différent à chaque appel.

int setvbuf(FILE *stream, char *buf, int mode, size_t size);


setvbuf contrôle la mise en mémoire tampon pour le flot stream. Il faut l'appeler avant
la première lecture ou écriture sur ce flot.
Différentes valeurs de mode:
_IOFBF provoque un tamponnage complet
_IOLBF provoque un tamponnage par lignes de fichier texte
_IONBF pas de tamponnage

void setbuf(FILE *stream, char *buf);


Si buf vaut NULL, setbuf stoppe la mémoire tampon pour le flot stream. Sinon, elle
équivaut à (void) setvbuf(stream, buf, _IOFBF, BUFSIZ).

PS/LANGAGES Page 76
Autres fonctions de la bibliothèque standard

11. AUTRES FONCTIONS DE LA BIBLIOTHEQUE STANDARD

11.1 Les tests de catégories de caractères : <ctype.h>


Le fichier d'en-tête <ctype.h> contient des déclarations de fonctions destinées à tester
les caractères. Pour chaque fonction, l'argument et la valeur de retour sont de type int. Ces
fonctions retournent une valeur non nulle (VRAI) si l'argument c remplit la condition ou 0
sinon.

isalnum(c) isalpha(c) ou isdigit(c) est vrai


isalpha(c) isupper(c) ou islower(c) est vrai
iscntrl(c) caractère de contrôle
isdigit(c) chiffre décimal
isgraph(c) caractère imprimable sauf l'espace
islower(c) lettre minuscule
isprint(c) caractère imprimable y compris l'espace
ispunct(c) caractère imprimable différent de l'espace, des lettres et des chiffres
isspace(c) espace, saut de page, fin de ligne, retour chariot, tabulations
isupper(c) lettre majuscule
isxdigit(c) chiffre hexadécimal
isascii(c) vrai si c est compris entre 0 et 127 (fonction non ANSI)

Les fonctions suivantes permettent des conversions

int toascii(int c) convertit c en un entier compris entre 0 et 127 (fonction non ANSI)
int tolower(int c) convertit c en minuscule
int toupper(int c) convertit c en majuscule

Si c est une lettre majuscule, tolower(c) retourne la lettre minuscule correspondante


sinon elle retourne c.
Si c est une lettre minuscule, toupper(c) retourne la lettre majuscule correspondante
sinon elle retourne c.

PS/LANGAGES Page 77
Autres fonctions de la bibliothèque standard

11.2 Les fonctions mathématiques : <math.h>


Le fichier d'en-tête <math.h> contient des déclarations de fonctions et de macros
mathématiques.

Pour chaque fonction, x et y sont de type double, i est de type int et toutes les valeurs de
retour sont de type double.

sin(x) sinus de x
cos(x) cosinus de x
tan(x) tangente de x
asin(x) arc sinus de x dans l'intervalle [-π/2, π/2], x ∈ [-1,1]
acos(x) arc cosinus de x dans l'intervalle [0, π], x ∈ [-1,1]
atan(x) arc tangente de x dans l'intervalle [-π/2, π/2]
atan2(y,x) arc tangente de y/x dans l'intervalle [-π, π]
sinh(x) sinus hyperbolique dex
cosh(x) cosinus hyperbolique dex
tanh(x) tangente hyperbolique dex
exp(x) fonction exponentielle de x = ex
log(x) logarithme népérien de x = ln(x), x > 0
log10(x) logarithme à base 10 = log10(x), x > 0
pow(x,y) xy
sqrt(x) x, x ≥ 0
ceil(x) le plus petit entier supérieur ou égal à x, exprimé en double
floor(x) le plus grand entier inférieur ou égal à x, exprimé en double
fabs(x) valeur absolue de x : |x|
ldexp(x,n) x.2n
frexp(x, int *exp) sépare x en une fraction dans l'intervalle[1/2,1] qui est retournée et une
puissance de 2 qui est placée dans *exp.
modf(x, double *ip) sépare x en ses parties entière placée dans *ip et fractionnaire qui est
retournée.
fmod(x,y) reste de x/y, exprimé en virgule flottante

PS/LANGAGES Page 78
Autres fonctions de la bibliothèque standard

11.3 Les fonctions utilitaires : <stdlib.h>


Le fichier d'en-tête <stdlib.h> contient des déclarations de fonctions traitant la
conversion des nombres et l'allocation de mémoire.

double atof(const char *s);


convertit une chaîne s en un double.

int atoi(const char *s);


convertit une chaîne s en un int.

long atol(const char *s);


convertit une chaîne s en un long.

double strtod(const char *s, char **endp);


convertit le début de la chaîne s en un double. Elle place dans *endp un pointeur
sur la partie non convertie sauf si endp vaut NULL.

long strtol(const char *s, char **endp, int base);


convertit le début de la chaîne s en un long. Elle place dans *endp un pointeur sur
la partie non convertie sauf si endp vaut NULL. Si base vaut 0, la base est 8,10 ou 16.
unsigned long strtoul(const char *s, char **endp, int base);
idem strtol mis à part les types des arguments et du résultat.

int rand(void);
retourne un entier pseudo-aléatoire compris entre 0 et RAND_MAX.

void srand(unsigned int seed);


prend seed comme amorce de la nouvelle séquence de nombres pseudo-aléatoires.
L'amorce initiale vaut 1.

void abort(void);
provoque un arrêt anormal du programme.

void exit(int status);


provoque l'arrêt normal du programme. L'écriture des tampons associés aux
fichiers ouverts est forcée. Les flots ouverts sont fermés. La façon dont status est retourné
dépend de l'implémentation.

void atexit(void (*fcn)(void));


enregistre que la fonction fcn devra être appelée lors de l'arrêt normal du
programme. Retourne une valeur non nulle si cet enregistrement n'est pas réalisable.

int system(const char *s);


passe la chaîne s à l'environnement pour que celui-ci l'exécute. La valeur de retour
dépend de l'implémentation.

char *getenv(const char *name);


retourne la chaîne d'environnement associée à name.

PS/LANGAGES Page 79
Autres fonctions de la bibliothèque standard

void bsearch(const void *key, const void *base, size_t n, size_t size,
int (*cmp)(const void *keyval, const void *datum));
recherche parmi base[0]..base[n-1] un objet s'identifiant à la clé *key. La
fonction cmp doit retourner une valeur négative, nulle ou positive en fonction de la
comparaison des clés. Les objets du tableau base doivent être rangés dans l'ordre croissant.
bsearch retourne un pointeur sur un objet identique à la clé ou NULL s'il n'en existe aucun.

void qsort(void *base, size_t n, size_t size, int (*cmp)(const void *, const void *));
trie dans l'ordre croissant un tableau base[0]..base[n-1] d'objets de taille size. La
fonction cmp doit retourner une valeur négative, nulle ou positive en fonction de la
comparaison des clés.

int abs(int n);


retourne la valeur absolue de son argument de type int.

long labs(long n);


retourne la valeur absolue de son argument de type long.

div_t div(int num, int denom)


calcule le quotient et le reste de la division de num par denom. Le quotient et le
reste sont placés dans les champs quot et rem de type int d'une structure de type div_t.

ldiv_t ldiv(long num, long denom);


calcule le quotient et le reste de la division de num par denom. Le quotient et le
reste sont placés dans les champs quot et rem de type long d'une structure de type ldiv_t.

11.4 Les listes variables d'arguments : <stdarg.h>


Le fichier d'en-tête <stdarg.h> permet à une fonction d'utiliser une liste d'arguments de
nombre et de types inconnus.
void va_start(va_list ap, lastfix);
type va_arg(va_list ap, type);
void va_end(va_list ap);

Les macros de la famille va_arg, va_end et va_start fournissent un moyen portable


d'accéder à ces listes d'arguments.
_ va_start fait pointer ap sur le premier argument fourni à la fonction.

_ va_arg génère une expression de même type et valeur que le prochain argument
transmis (un des arguments variables).

_ va_end facilite le travail de retour normal de la fonction appelée.

ap Pointe sur la liste va_list transmise


ap de va_arg doit être le même que celui initialisé par va_start
lastfix Nom du dernier paramètre fixe transmis
type Sert à va_arg pour déréférencer et situer l'élément suivant

PS/LANGAGES Page 80
Autres fonctions de la bibliothèque standard

11.5 Les fonctions de traitement de la date et de l'heure : <time.h>


Le fichier d'en-tête <time.h> contient des déclarations de types et de fonction servant à
manipuler l'heure et la date. clock_t et time_t sont des types arithmétiques qui représentent
des instants et struct tm contient les composants d'une heure calendaire:

int tm_sec; secondes après la minute (0-61)


int tm_min; minutes après l'heure (0-59)
int tm_hour; heures depuis minuit (0-23)
int tm_mday; jour du mois (1-31)
int tm_mon; mois depuis janvier (0-11)
int tm_year; année depuis 1900
int tm_wday; jours depuis dimanche (0-6)
int tm_yday; jours depuis le 1er janvier (0-365)
int tm_isdst; drapeau de l'heure d'été (positif si heure d'été nul sinon)

clock_t clock(void);
retourne le temps d'utilisation par le programme depuis le début de son exécution.

time_t time(time_t *tp);


retourne l'heure calendaire actuelle. *tp reçoit aussi cette valeur de retour.

double difftime(time_t time2, time_t time1);


retourne la durée time2 - time1, exprimée en secondes.

time_t mktime(struct tm *tp);


convertit l'heure locale contenue dans la structure *tp en heure calendaire.
Retourne l'heure calendaire.

char *asctime(const struct tm *tp);


convertit l'heure représentée dans la structure *tp en une chaîne de la forme:
Sun Jan 3 15:14:17 1997\n\0

char *ctime(const time_t *tp);


convertit l'heure calendaire *tp en heure locale.

struct tm *gmtime(const time_t *tp);


convertit l'heure calendaire en Temps Universel.

struct tm *localtime(const time_t *tp);


convertit l'heure calendaire *tp en heure locale.

PS/LANGAGES Page 81
Autres fonctions de la bibliothèque standard

size_t strftime(char *s, size_t smax, const char *fmt, const struct tm *tp);
transforme les informations de date et d'heure contenues dans *tp suivant le
format fmt (analogue à un format de printf) et place le résultat dans s. strftime place au
maximum smax caractères dans s.

Caractères de conversion pour strftime:


%a abréviation du jour de la semaine
%A nom complet du jour de la semaine
%b abréviation du mois
%B nom complet du mois
%c représentation locale de la date et de l'heure
%d jour du mois (01-31)
%H heure (0-23)
%I heure (01-12)
%j numéro du jour dans l'année (001-366)
%m numéro du mois (01-12)
%M minutes (00-59)
%p équivalent local de AM ou PM
%S secondes (00-59)
%U numéro de la semaine dans l'année
%w numéro du jour de la semaine (0-6) 0 = dimanche
%W numéro de la semaine dans l'année
%x représentation locale de la date
%X représentation locale de l'heure
%y année dans le siècle (00-99)
%Y année y compris le siècle
%Z nom du fuseau horaire
%% %

11.6 Les limites définies par l'implémentation : limits.h, values.h et float.h


Le fichier d'en-tête <limits.h> définit des constantes pour les tailles des types entiers.
Ces valeurs sont fonction de l'implémentation.
CHAR_BIT 8 bits par caractère
CHAR_MAX UCHAR_MAX ou SCHAR_MAX valeur maximum d'un char
CHAR_MIN 0 ou SCHAR_MIN valeur minimum d'un char
INT_MAX +2147483647 valeur maximale d'un int
INT_MIN -2147483648 (-(INT_MAX+1))
LONG_MAX +2147483647 valeur maximale d'un long
LONG_MIN -2147483648 (-(LONG_MAX+1))
SCHAR_MAX +127 valeur maximale d'un signed char
SCHAR_MIN -128 (-(SCHAR_MAX+1))
SHRT_MAX +32767 valeur maximale d'un short
SHRT_MIN -32768 (-(SHRT_MAX+1))
UCHAR_MAX 255 valeur maximale d'un unsigned char
UINT_MAX 4294967295 valeur maximale d'un unsigned int
ULONG_MAX 4294967295 valeur maximale d'un unsigned long
USHRT_MAX 65535 valeur maximale d'un unsigned short

PS/LANGAGES Page 82
Autres fonctions de la bibliothèque standard

Valeurs définies dans <values.h>

HIBITS ((short)-32768)
HIBITI ((int)-2147483648)
HIBITL ((long)-2147483648)
MAXSHORT ((short)~HIBITS)
MAXINT ((int)~HIBITI)
MAXLONG ((long)~HIBITL)
MAXFLOAT ((float)3.40282346638528860e+38)
MINDOUBLE 4.94065645841246544e-324
MINFLOAT ((float)1.40129846432481707e-45)
M_PI 3.14159265358979323846264338327950288
M_SQRT2 1.41421356237309504880168872420969808

Le fichier <float.h> contient des déclarations de constantes relatives à l'arithmétique en


virgule flottante.
Constantes Valeurs courantes Signification
FLT_MAX 3.4028234663852886e+38F le plus grand nombre float
FLT_MIN 1.1754943508222875e-38F le plus petit nombre float
FLT_DIG 6 précision en chiffres décimaux
FLT_ROUNDS ( fp_read_rnd() ) mode d'arrondi pour l'addition
FLT_RADIX 2 base de la représentation (base 2)
FLT_MANT_DIG 24 nombre de chiffres de la mantisse
FLT_EPSILON 1.1920928955078125e-7F le plus petit x ; 1.0 + x ≠ 1.0
FLT_MIN_EXP -125 le plus petit exposant pour 10n
FLT_MAX_EXP 128 le plus grand exposant n pour que
FLT_RADIXn-1 soit représentable
DBL_MAX 1.7976931348623158e+308 le plus grand nombre double
DBL_MIN 2.2250738585072014e-308 le plus petit nombre double
DBL_DIG 15 précision en chiffres décimaux
DBL_MANT_DIG 53 nombre de chiffres de la mantisse
DBL_EPSILON 2.2204460492503131e-16 le plus petit x ; 1.0 + x ≠ 1.0
DBL_MIN_EXP -1021 le plus petit exposant pour 10n
DBL_MAX_EXP 1024 le plus grand exposant n pour que
FLT_RADIXn-1 soit représentable

PS/LANGAGES Page 83
Autres fonctions de la bibliothèque standard

11.7 Le fichier errno.h


Le fichier errno.h contient les différentes valeurs que peut prendre la variable errno.

EPERM Operation not permitted


ENOENT No such file or directory
ESRCH No such process
EINTR interrupted system call
EIO I/O error
ENXIO No such device or address
E2BIG Arg list too long
ENOEXEC Exec format error
EBADF Bad file descriptor
ECHILD No child processes
EAGAIN Resource temporarily unavailable
ENOMEM Not enough space
EACCES Permission denied
EFAULT Bad address
ENOTBLK Block device required
EBUSY Resource busy
EEXIST File exists
EXDEV Improper link
ENODEV No such device
ENOTDIR Not a directory
EISDIR Is a directory
EINVAL Invalid argument
ENFILE Too many open files in system
EMFILE Too many open files
ENOTTY Inappropriate I/O control operation
ETXTBSY Text file busy
EFBIG File too large
ENOSPC No space left on device
ESPIPE Invalid seek
EROFS Read only file system
EMLINK Too many links
EPIPE Broken pipe
EDOM Domain error within math function
ERANGE Result too large
ENOMSG No message of desired type
EIDRM Identifier removed
ECHRNG Channel number out of range
EL2NSYNC Level 2 not synchronized
EL3HLT Level 3 halted
EL3RST Level 3 reset
ELNRNG Link number out of range
EUNATCH Protocol driver not attached
ENOCSI No CSI structure available
EL2HLT Level 2 halted
EDEADLK Resource deadlock avoided
ENOTREADY Device not ready
EWRPROTECT Write-protected media
EFORMAT Unformatted media
ENOLCK No locks available
ENOCONNECT no connection
ESTALE no filesystem
EDIST old, currently unused AIX errno

PS/LANGAGES Page 84
Autres fonctions de la bibliothèque standard

11.8 Les fonctions, constantes et types de la bibliothèque conio.h

cgets char *cgets(char *str);

Lit une chaîne depuis le clavier. Effectue la lecture d'une chaîne de caractères depuis la
console, en stockant la chaîne et sa longueur dans la position pointée par *str. cgets lit les
caractères jusqu'à la rencontre du couple retour chariot/saut de ligne (CR/LF). ou jusqu'à
atteindre le nombre de caractères maximal. str[0] doit contenir la longueur maximale de la
chaîne à lire. Au retour, str[1] contient le nombre de caractères réellement lus. Les caractères
commencent à str[2] et se terminent par un caractère nul terminal. str doit donc avoir une
longueur équivalente à str[0] plus 2 octets au minimum.
Valeur Renvoyée: Un pointeur sur str[2] en cas de succès.

cputs int cputs(const char *str);

Affiche une chaîne dans la fenêtre texte courante. Ecrit la chaîne à zéro terminal str dans la
fenêtre texte active. N'ajoute pas de caractère de saut de ligne. La chaîne est écrite soit
directement en mémoire vidéo, soit par un appel BIOS, en fonction de la valeur de la variable
globale directvideo. A la différence de puts, cputs ne convertit pas les caractères de saut de
ligne (\n) en un couple retour-chariot/saut de ligne (\r\n).
Valeur Renvoyée: Le dernier caractère affiché.

clreol void clreol(void);

Efface la fin de la ligne dans la fenêtre texte. clreol efface tous les caractères de la position du
curseur à la fin de la ligne au sein de la fenêtre texte active, sans déplacer le curseur.

clrscr void clrscr(void);

Efface la fenêtre texte. clrscr efface le contenu de la fenêtre texte active et ramène le curseur
dans le coin supérieur gauche (1,1).

cprintf int cprintf (const char *format [, argument, ...]);

Avec cprintf, la chaîne est envoyée soit directement en mémoire vidéo, soit via un appel au
BIOS, en fonction de la valeur de directvideo. cprintf ne convertit pas les sauts de ligne
(Linefeed, \n) en couples Carriage-return/linefeed (\r\n).

cscanf int cscanf (char *format [, address, ...]);

Identique à scanf

delline void delline(void);

Efface une ligne dans la fenêtre texte. delline efface la ligne contenant le curseur; toutes les
lignes suivantes sont décalées d'une position vers le haut. La portée de delline est limitée à la
fenêtre texte courante.

PS/LANGAGES Page 85
Autres fonctions de la bibliothèque standard

getch, getche int getch(void);


int getche(void);

getch renvoie un caractère lu au clavier, sans écho à l'écran.


getche renvoie un caractère lu au clavier, avec écho à l'écran.
getch lit un unique caractère provenant du clavier, sans l'afficher.
getche lit un unique caractère provenant du clavier et l'affiche dans la fenêtre texte active en
utilisant le service d'affichage vidéo direct ou le BIOS.
Valeur Renvoyée: Toutes deux renvoient le caractère lu au clavier.

getpass char *getpass(const char *prompt);

Lit un mot de passe au clavier. Après avoir affiché la chaîne de caractères invite (chaîne
terminée par un caractère d'arrêt nul) et désactivé l'écho, getpass lit un mot frappé au clavier.
Ce mot est placé dans une chaîne dont la taille maximale est de huit caractères (non compris
le caractère nul d'arrêt).
Valeur Renvoyée: Un pointeur sur la chaîne contenant le mot de passe, c'est la même chaîne
statique qui est utilisée à chaque appel.

gettext, puttext int gettext(int left, int top, int right, int bottom, void*destin);
int puttext(int left, int top, int right, int bottom, void*source);

gettext recopie le contenu d'un rectangle à l'écran délimité par (left, top) et (right, bottom)
dans la zone mémoire *destin.
puttext recopie le contenu de *source dans le rectangle à l'écran délimité par (left, top) et
(right, bottom). puttext réalise un accès direct à la mémoire vidéo.
Ces fonctions travaillent séquentiellement de gauche à droite et de haut en bas.
Les coordonnées écran sont absolues et non relatives à une fenêtre texte.
L'origine de l'écran est en (1,1).
Chaque position occupe 2 octets en mémoire (caractère/attribut).
Le 1er octet est le caractère.
Le second est l'attribut vidéo.
L'espace mémoire à prévoir pour un rectangle de w colonnes sur h lignes est donc de:
espace = (h lignes) * (w colonnes) * 2
Valeur Renvoyée: Si succès
gettext renvoie 1
puttext renvoie != 0
Si erreur, les deux fonctions renvoient 0

gettextinfo void gettextinfo(struct text_info *r);

Donne des informations sur le mode texte courant. gettextinfo renseigne une structure avec
les information vidéo du mode texte en vigueur.
r pointe sur text_info (structure réceptrice)

gotoxy void gotoxy(int x, int y);

Positionne le curseur dans la fenêtre texte. gotoxy place le curseur à la position de l'écran
spécifiée (relative au système de coordonnées de la fenêtre active). Si les coordonnées ne sont
pas valides, l'appel à gotoxy est ignoré.

PS/LANGAGES Page 86
Autres fonctions de la bibliothèque standard

highvideo, lowvideo, normvideo void highvideo(void);


void lowvideo(void);
void normvideo(void);

Activent des attributs vidéo pour l'affichage des caractères.


highvideo Affichage en sur-intensité.
lowvideo Affichage en faible intensité.
normvideo Affichage en intensité normale.

insline void insline(void);

Insère une ligne vide dans la fenêtre texte. Dans une fenêtre texte, insline insère une ligne
vierge à la position du curseur. Toutes les lignes placées sous la ligne insérée sont décalées
d'une ligne vers le bas et la dernière ligne est effacée de l'écran.

inp, inpw, outp, outpw int inp(unsigned portid);


unsigned inpw(unsigned portid);
int outp(unsigned portid, int value);
unsigned outpw(unsigned portid, unsigned value);

inp lit un octet sur un port d'entrée matériel


inpw lit un mot sur un port d'entrée matériel
outp écrit un octet sur un port d'entrée matériel
outpw lit un mot sur un port d'entrée matériel
inp et inpw sont des macros qui scrutent le port portid.
outp et outpw sont des macros qui écrivent sur le port portid.

inport, inportb, outport, outportb <DOS.H>

inport lit un mot d'un port matériel


inportb lit un octet d'un port matériel
outport écrit un mot dans un port matériel
outportb écrit un octet dans un port matériel
inport fonctionne comme l'instruction 80x86 IN. Elle lit l'octet de poids faible du mot à
portid, et celui de poids fort de portid + 2.
outport fonctionne comme l'instruction 80x86 OUT. Elle écrit l'octet de poids faible de value
dans portid, et celui de poids fort dans portid + 1.

kbhit int kbhit(void);

Teste une éventuelle frappe au clavier. kbhit teste si un caractère est disponible à la suite
d'une frappe au clavier. Si c'est le cas, ce caractère peut être lu par getch ou getche.

movetext int movetext(int left, int top, int right, int bottom, int destleft, int desttop);

Recopie une zone rectangulaire de texte d'un emplacement de l'écran vers un autre. movetext
recopie le contenu du rectangle de l'écran défini par gauche, haut, droit et bas vers un
nouveau rectangle de mêmes dimensions. La position du coin supérieur du nouveau rectangle
est (dest_gauche, dest_haut). Toutes les coordonnées sont absolues. Les rectangles source et
destination peuvent se chevaucher, la recopie se fera correctement.
Valeur Renvoyée: En cas de succès, renvoie une valeur non nullle.
putch int putch(int ch);

PS/LANGAGES Page 87
Autres fonctions de la bibliothèque standard

Ecrit un caractère dans la fenêtre active de l'écran. putch écrit le caractère c sur l'écran, dans
la fenêtre texte courante. C'est une fonction effectuant des sorties directes sur la console en
mode texte. putch ne transforme pas le caractère de saut de ligne (\n) en séquence retour
chariot/saut de ligne (CR/LF).
Suivant la valeur de la variable globale directvideo, l'affichage s'effectue dans la mémoire
vidéo ou grâce à un appel au BIOS.
Valeur renvoyée: Si succès, putch renvoie c.
Si erreur, renvoie EOF.

_setcursortype void _setcursortype(int cur_t);

Sélectionne une forme de curseur.


_NOCURSOR (Pas de curseur)
_SOLIDCURSOR (Curseur rectangle plein)
_NORMALCURSOR (Curseur normal, signe de soulignement)

textattr, textbackground, textcolorÌ void textattr(int newattr);


void textbackground(int newcolor);
void textcolor(int newcolor);

Contrôlent les attributs et couleurs d'affichage des textes en mode texte. Ces fonctions
s'associent à celles d'affichage direct à l'écran en mode texte. textattr permet de modifier les
couleurs de fond et de caractère en un seul appel. (Les attributs peuvent aussi être modifiés
séparément par textcolor et textbackground.)
Ces fonctions n'ont pas d'effet sur les caractères déjà affichés à l'écran; elles n'affectent que
ceux qui seront affichés par les fonctions d'écriture directe sur la console (comme cprintf),
après l'appel.
Codage de la couleur dans newattr (argument de textattr):

7 6 5 4 3 2 1 0
C f f f c c c c

Dans les 8 bits de newattr,


cccc est la couleur des caractères sur 4 bits (valeurs entre 0 et 15),
fff est la couleur du fond sur 3 bits, (valeurs entre 0 et 7),
C est le bit de clignotement.

Le clignotement des caractères s'obtient en armant le bit approprié, ou bien en ajoutant la


constante symbolique BLINK à l'attribut. (Exemple : textcolor(RED + BLINK))

textmode void textmode(int newmode);

Sélectionne un mode texte spécifique. Le mode texte choisi peut être spécifié dans l'argument
newmode grâce à une constante symbolique du type énuméré text_modes (définie dans
CONIO.H). Quand textmode est appelée, la fenêtre courante est réinitialisée à l'ensemble de
l'écran et les attributs courants d'affichage sont remis à leurs valeurs normales, ce qui
correspond à un appel à normvideo. L'appel de textmode avec LASTMODE comme
argument permet de resélectionner le dernier mode texte sélectionné.

PS/LANGAGES Page 88
Autres fonctions de la bibliothèque standard

ungetch int ungetch(int ch);

Réinjecte un caractère dans le tampon du clavier. ungetch replace le caractère ch dans le


tampon du clavier, de telle sorte qu'il redevienne le prochain caractère à lire.
Valeur renvoyée: Si succès, renvoie le caractère ch, sinon renvoie EOF.

wherex, wherey int wherex(void);


int wherey(void);

wherex renvoie l'abcisse de la position actuelle du curseur dans la fenêtre texte courante.
wherey renvoie l'ordonnée de la position actuelle du curseur dans la fenêtre texte courante.

Valeur renvoyée : wherex renvoie un entier compris entre 1 et 80.


wherey renvoie un entier compris entre 1 et 25 ,1 et 43 ou 1 et 50
(selon le mode vidéo).

window void window(int left, int top, int right, int bottom);

Définit une fenêtre d'affichage en mode texte. Le coin supérieur gauche de l'écran est en
(1,1). window définit une fenêtre texte à l'écran. Si les coordonnées transmises comme
paramètres ne sont pas valables, l'appel à cette fonction est ignoré. (left, top) est la
coordonnée (x, y) du coin supérieur gauche de la fenêtre. (right, bottom) est la coordonnée (x,
y) de son coin inférieur droit. La taille minimale d'une fenêtre texte est d'une ligne sur une
colonne.

PS/LANGAGES Page 89
Autres fonctions de la bibliothèque standard

COLORS, CGA_COLORS, EGA_COLORS (Constantes de couleurs énumérées)

Ces tables montrent :


- les constantes symboliques servant aux attributs des textes en modes CGA et EGA.
- les couleurs de tracé des fonctions BGI en modes CGA et EGA (GRAPHICS.H.)
Les constantes COLORS servent à ces fonctions en mode texte: textattr, textbackground,
textcolor.

COLORS (mode texte)

BLACK 0
BLUE 1
GREEN 2
CYAN 3
RED 4
MAGENTA 5
BROWN 6
LIGHTGRAY 7
DARKGRAY 8
LIGHTBLUE 9
LIGHTGREEN 10
LIGHTCYAN 11
LIGHTRED 12
LIGHTMAGENTA 13
YELLOW 14
WHITE 15
BLINK * 128

* Pour le clignotement en mode texte, ajoutez BLINK à la couleur de caractère


(foreground color).

PS/LANGAGES Page 90
Utilitaires

12. UTILITAIRES

12.1 Gestion de projets


Le langage C s'appuie sur la structuration au niveau des fichiers. Le programmeur va
devoir recompiler les différents fichiers à chaque fois qu'il effectuera des modifications sur
l'un de ces fichiers. Il apparaît intéressant de ne recompiler que les fichiers ayant subi des
modifications. Pour cela on utilisera un gestionnaire de projets: le make.

12.1.1 Make
L'utilitaire make s'appuie sur un fichier texte appelé makefile qui indique les
dépendances, ou relations entre les différents fichiers. Par défaut, make cherche dans le
répertoire de l'utilisateur un fichier makefile ou Makefile.

Si le fichier makefile n'existe pas dans le répertoire courant, la commande suivante


$make prog
génère la commande suivante:
cc prog.c -O -o prog
En l'absence de fichier makefile, des règles implicites sont appliquées.

Exemple de fichier makefile:


# make de maintenance de l'application prog
prog: initial.o princ.o
cc -o prog initial.o princ.o
initial.o: initial.c initial.h princ.h
cc -c initial.c
princ.o: princ.c princ.h
cc -c princ.c

Lancement:
$make -f makefile prog ou plus simplement
$make

Ce fichier est constitué d'une ligne de commentaires commençant par #, de premières


lignes de dépendances directes et de deuxièmes lignes de commandes de compilation
(commençant impérativement par une tabulation).

Le résultat de la compilation sera le fichier prog.


Ce programme dépend de initial.o et princ.o. Si l'un de ces fichiers est plus récent que
prog, la ligne de commande cc -o prog initial.o princ.o sera exécutée pour recréer un nouvel
exécutable.

De la même façon, initial.o dépend de initial.c, initial.h et princ.h

PS/LANGAGES Page 91
Utilitaires

12.1.1.1 Syntaxe des fichiers makefile


# Commentaire jusqu'à la fin de la ligne
chaine1=chaine2 $(chaine1) vaut chaine2
$(chaine1:val1=val2) Remplace val1 par val2 dans chaine1

Exemples:
OFILE=x.o y.o z.o
...
applic:$(OFILE)
cc $(OFILE) -O -o applic

$(OFILE:.o=.c) vaut x.c y.c z.c

12.1.1.2 Les macros prédéfinies


$@ le nom complet du fichier cible
$* le nom du fichier sans suffixe
$? liste des fichiers pré-requis dont la date est postérieure à celle de l'objectif
$% évalué seulement quand l'objectif est membre d'une librairie
$< le nom du fichier dépendance dans les règles implicites

12.1.1.3 Options du make


-f nom nom du fichier de description du makefile
-p afficher les macros et les règles prédéfinies
-n afficher les commandes et ne pas les exécuter
-i les codes d'erreurs des commandes exécutées sont ignorés
-r ne tient pas compte des règles implicites
-d debug : des informations sont données sur les fichiers et les dates
-s les commandes sont exécutées sans être affichées

PS/LANGAGES Page 92
Utilitaires

12.1.2 Gestion de projets sous TURBO C


TURBO C permet de gérer des projets selon deux modes:
• En mode ligne de commande avec un utilitaire make qui fonctionne sensiblement
comme le make d'UNIX.
• Au sein de l'EDI grâce au menu PROJECT.

Au sein de l'EDI, le gestionnaire de projets permet:


• L'assemblage automatique de tous les modules
• L'édition des différents fichiers sources ou d'en-tête associés au projet
• La création automatique d'un fichier de type makefile qui a pour extension .PRJ.

Lorsque l'on reconstruit un projet, le gestionnaire met à jour automatiquement les


informations du fichier projet.

Utilisation du gestionnaire de projets


• Choisir un nom pour le projet (dans PROJECT/OPEN PROJECT).
• Ajouter les noms de fichiers source dans la boite de dialogue PROJECT/ADD ITEM.
• Lancer la compilation au moyen de COMPILE/MAKE.

Ensuite, vous pouvez


• ajouter (ou enlever) des fichiers a votre projet
• définir les options pour un fichier du projet
• visualiser les fichiers inclus

12.2 L'utilitaire LINT


Cet utilitaire permet de vérifier la syntaxe d'un fichier source c. Il n'effectue pas de
modifications et ne génère pas de programme exécutable.
Il vérifie la syntaxe des instructions et signale celles qui pourraient poser un problème
de portabilité.
Il effectue un contrôle approfondi des types de données.
Utilisation:
lint fichier.c
Pour les différentes options se reporter à la documentation ou à l'aide en ligne.

PS/LANGAGES Page 93
Utilitaires

12.3 Débogage des programmes sous UNIX


UNIX propose des débogueurs (SDB ou DBX plus convivial).
Il est souvent nécessaire de passer par une phase de mise au point d'un programme. Le
débogueur symbolique est un outil qui aide à la mise au point des programmes C en
permettant
⇒ d'examiner des variables
⇒ de poser des points d'arrêts
⇒ d'exécuter pas à pas etc...

12.3.1 Utilisation de DBX


Pour débogger un programme, il faut le compiler avec l'option -g
$cc -g fichier.c -o ficexec
puis exécuter le programme DBX de la façon suivante:
$dbx ficexec (a.out par défaut)

On peut définir les options par défaut ou des alias en utilisant le fichier .dbxinit
Exemple:
alias p print
alias rr rerun
alias c cont
alias d dump
set $listwindow=20

Le prompt de dbx est (dbx).

12.3.2 Lancement et sortie


r[arguments] Lancement [avec arguments]
s Exécution pas à pas (step)
rerun Relance après une exécution
c Continue l'exécution jusqu'au prochain point d'arrêt
n Exécute la ligne suivante. Next équivaut à Step over
q ou quit Sortie de dbx

PS/LANGAGES Page 94
Utilitaires

12.3.3 Pose de points d'arrêts


stop 100 Pose un point d'arrêt à la ligne 100
stop at 100 if var == 2 Pose un point d'arrêt à la ligne 100 si var vaut 2
stop in fonc Pose un point d'arrêt sur la première instruction de fonc
status Affiche tous les points d'arrêts
delete num Supprime le point d'arrêt de la ligne num
delete all Supprime tous les points d'arrêts
clear num Supprime le point d'arrêt de la ligne num

12.3.4 Principales commandes d'édition


(dbx)list ou l Edite les 10 lignes suivantes (ou 20 si $listwindow=20)
(dbx)l n Edite la ligne numéro n
(dbx)l 10, 15 Edite les lignes de 10 à 15
(dbx)/nom/ Recherche avant et édition de la ligne contenant nom
(dbx)?nom? Recherche arrière et édition de la ligne contenant nom
(dbx) e Edite sous 'vi' le programme en debug

12.3.5 Edition du source en cours de debug


(dbx) l $ Edite la ligne courante en exécution
(dbx) l @ Affiche la ligne qui sera exécutée après la ligne courante
(dbx) l $-n, $+n Edite les +- n lignes qui encadrent la ligne courante

12.3.6 Examen des variables du programme


(dbx)print &var Affiche l'adresse de var
(dbx)print var Affiche le contenu de var
(dbx)print *var Si var est un pointeur, affiche ce qui est pointé par var
(dbx)print st.membre Affiche le membre de la structure st
(dbx)print tablo Affiche tablo
(dbx)print tablo [0..2] Affiche les éléments de 0 à 2 de tablo

12.3.7 Commandes diverses


(dbx)assign var = val Assigne la valeur val à la variable var
(dbx)print sizeof var Affiche la taille en octets de var
(dbx)where Affiche l'empilement des fonctions appelées
(dbx)whereis x Indique où est déclarée la variable x (fichier.main.x)
(dbx)whatis x Indique la nature de la variable x (int x)
(dbx)dump Affiche les noms et les valeurs des variables
(dbx)alias Liste des alis de dbx
(dbx)set Liste des variables internes de dbx
(dbx)trace Trace l'exécution du programme instruction par instruction
pour une ligne, une fonction ou le programme

PS/LANGAGES Page 95
Utilitaires

12.4 Débogage des programmes sous TURBO C


TURBO C, grâce au multi-fenêtrage permet de faire apparaître sur l'écran plusieurs
fenêtres dont l'une est réservée au débogage.
TURBO C propose plusieurs manières de suivre l'exécution d'un programme.

12.4.1 Principales commandes


F7 (ou menu RUN/TRACE INTO)
Chaque frappe sur la touche F7 fait exécuter la ligne d'instructions. La prochaine ligne à
exécuter est mise en surbrillance.
Lorsque la ligne d'instruction exécutée est un appel de fonction, cette dernière est
exécutée en mode pas à pas.

F8 (ou menu RUN/STEP OVER)


Idem que F7 mais lorsque la ligne d'instruction est un appel de fonction, la fonction est
exécutée d'un coup.
On peut basculer de F7 à F8 et inversement.

F4 (ou menu RUN/GO TO CURSOR)


Exécute le programme jusqu'à la ligne sur laquelle est positionné le curseur.
On peut mettre fin à l'exécution du programme par CTRL-BREAK.

12.4.2 Actions sur les variables


A l'aide du menu DEBUG/ADD WATCH ou CTRL-F7, on peut entrer le nom des
variables que l'on souhaite visualiser.

On peut également évaluer (et/ou modifier) une variable au cours du débogage à l'aide
de la commande menu DEBUG/EVALUATE ou CTRL-F4.

On peut aussi inspecter une variable à l'aide de menu DEBUG/INSPECT. Le contenu


affiché indique alors le nom de la variable, son adresse et le type de donnée.

12.4.3 Points d'arrêts


Comme dans tous les débogueurs, on peut mettre en place des points d'arrêts à l'aide de
la commande menu DEBUG/BREAKPOINTS... ou DEBUG/TOOGLE BREAKPOINTS
(CTRL-F8). Ces points d'arrêts peuvent être conditionnels (menu BREAKPOINTS... puis
EDIT).

12.5 Gestionnaires de bibliothèques


Une bibliothèque est un groupe de fichiers géré comme un fichier unique par le
système. Chaque membre de la bibliothèque est désigné par son nom d'origine.

Un fichier de tout peut être rangé en bibliothèque.

Utilisation : les binaires objets (.o) utilisés par l'éditeur de liens.

PS/LANGAGES Page 96
Utilitaires

12.5.1 L'utilitaire ar (UNIX)


Généralement les bibliothèques sont dotés du suffixe .a.
Exemples : /lib/libc.a bibliothèque standard
/lib/libm.a bibliothèque mathématique

Utilisation
$ar option nom_bibli [liste_fic]

Options
d suppression de membre(s) du fichier
r remplacement d'un membre
u contrôle de la date
q ajoute un membre en fin de fichier
t affiche le contenu de la bibliothèque
v mode verbose (bavard)
x extraction d'un membre

Exemple:
$ar -t /usr/libc.a affiche le contenu de libc.a
$ar ru biblio.a fonc1.o remplace fonc1.o dans biblio.a

12.5.2 L'utilitaire TLIB (TURBO C)


Permet de créer ou de maintenir des bibliothèques à partir de modules objets .OBJ
TLIB nom_biblio commande [liste_fic]

Commande
+ ajoute le (ou les) modules spécifiés
- retire de la bibliothèque le module désigné
* extraction de la bibliothèque sans effacer le module
-+ ou +- remplace le module dans la bibliothèque
-* ou *- extraction de bibliothèque et efface le module

PS/LANGAGES Page 97
Annexes

13. ANNEXES

13.1 UTILISATION DE VI

13.1.1 Présentation de VI
VI travaille selon deux modes:
• un mode commande divisé en deux sous-modes
- déplacement du curseur, mode insertion, copies, effacement etc..
- un autre sous-mode introduit par : qui permet d'accéder à certaines commandes
spéciales
• un mode texte utilisé pour entrer les différents caractères du fichier.

13.1.2 Spécification du type de terminal


VI doit connaître le type de terminal utilisé. On peut le spécifier à l'aide de la variable
TERM de l'environnement. Exemple:
$ TERM=vt320;export TERM

13.1.3 Configuration de VI
VI est paramétrable: on peut modifier certains de ses comportements (indentation,
numérotation des lignes, tabulations etc..) par la commande set.
Exemples
:set all : affiche toutes les options de configuration.
:set num : affiche la numérotation des lignes sous VI.
On peut paramétrer VI de façon permanente en spécifiant les options dans le fichier
$HOME/.exrc ou dans la variable d'environnement EXINIT.
Exemple de fichier de configuration:
set nu # affiche la numérotation des lignes
set showmode # affiche sur la dernière ligne l'état : INPUT MODE/ REPLACE
MODE etc...
set autoindent # met en oeuvre l'auto-indentation
set ts=4 # fixe la tabulation à 4 caractères

13.1.4 Entrée dans VI


$ vi [-options] [nom(s) de fichier(s)]
Si on appelle VI sans paramètre, il présente une page vierge. On peut alors charger
un fichier avec la commande :e nom_fich
Si le fichier existe, la première page de celui-ci est affichée.
Si le fichier spécifié n'existe pas, il est créé dans le répertoire courant et VI affiche
une page blanche.
Si plusieurs noms de fichiers sont spécifiés, VI affiche d'abord le premier.
Pour accéder au suivant :n
Pour basculer entre les deux derniers fichiers édités : CTRL-A ou :e#
Lorsqu'un fichier est édité, on peut charger un deuxième fichier (:e nouveau) et
basculer de l'un à l'autre grâce à CTRL-A ou :e#<RC>

PS/LANGAGES Page 98
Annexes

Les principales options


-R VI ouvre le fichier en lecture seule pour consultation
+5 VI ouvre le fichier spécifié à la ligne N°5
+/mot VI ouvre le fichier à la première occurrence de mot.
-r VI peut récupérer des données (un fichier) perdu à la suite d'un incident
(coupure de courant, fausse manœuvre etc..)

13.1.5 Sortie de VI
Avec sauvegarde:
ZZ ou :x
:w suivi de :q ou :wq

Sans sauvegarde:
:q si pas de modifications
:q! si modifications

Vers le Shell
:! commande ou
:sh
$ commandes
$ <CTRL>D

13.1.6 Création et insertion de texte


Insertion de texte dans une ligne
a<texte><ESC> Insertion de texte derrière le curseur. <ESC> sortie du mode
Insertion
i<texte><ESC> Insertion de texte avant le curseur.
A<texte><ESC> Insertion de texte en fin de ligne.
I<texte><ESC> Insertion de texte en début de ligne

Insertion de lignes
o<texte><ESC> Insertion d'une ligne à la suite de la ligne courante
O<texte><ESC> Insertion d'une ligne avant la ligne courante

PS/LANGAGES Page 99
Annexes

13.1.7 Déplacement du curseur dans un fichier


Sur caractères
 ou h ou backspace
 ou l ou espace
 ou k
 ou j ou linefeed

Sur lignes
^ Début de ligne
$ Fin de ligne
0 (zéro) Début de ligne physique
6| 6ème caractère de la ligne courante
CR Début de ligne suivante
- Début de ligne précédente

Sur écran
H Home (première ligne de l'écran)
L Dernière (Last)
M Milieu

Sur mots
w W Début du mot suivant
b B Début du mot courant
e E Fin du mot courant
Les commandes majuscules ne tiennent compte que des espaces et des tabulations
Les commandes minuscules tiennent compte des signes de ponctuation.

Sur phrase
( Début de la phrase courante
) Fin de la phrase courante Une phrase se termine par . ! ou ?

Sur paragraphe
{ Début du paragraphe
} Fin du paragraphe. Un paragraphe se termine par une ligne blanche.

Sur numéro de ligne


10G ou :10 se place ligne N° 10
G ou :$ se place sur la dernière ligne du fichier

Sur emplacement marqué


’’ (2 simples quotes) permet de se déplacer au dernier endroit marqué par ‘’
ma permet de nommer un emplacement (ici a)
‘a permet de se repositionner au début de la ligne marquée
`a permet de se repositionner à l’endroit du marquage (par exemple au
milieu de la ligne)

PS/LANGAGES Page 100


Annexes

13.1.8 Déplacement du curseur dans la fenêtre


z. Centrer sur la ligne courante
z<CR> Ligne courante en haut de l'écran
z- Ligne courante en bas de l'écran

^D Un demi écran vers la bas (Down)


^U Un demi écran vers le haut (Up)

^F Un écran (vers le bas Forward)


^B Un écran (vers le haut Backward)

^L Raffraîchit l'écran (après une modification)

13.1.9 Recherche de chaînes de caractères


La recherche se fait par
/chaîne en avant dans le fichier
?chaîne en arrière dans le fichier

Prochaine recherche
n dans le même sens qu'avant
N dans le sens inverse
// en avant dans le fichier
?? en arrière dans le fichier
% recherche le frère pour () , [] , {}

13.1.10 Destruction de texte


Destruction de caractères
x Détruit le caractère courant
3x Détruit 3 caractères
X Détruit le caractère précédent

Destruction de lignes
dd ou :d<RC> Détruit la ligne courante
5dd ou :5d<RC> Détruit 5 lignes
d$ ou D Détruit la fin de la ligne

Destruction de mots
dw Détruit le mot courant
3dw ou d3w Détruit 3 mots
d/chaîne Détruit jusqu'à la première occurrence de chaîne (non comprise)

PS/LANGAGES Page 101


Annexes

13.1.11 Remplacement de texte


rb Remplace le caractère courant par 'b'
R<texte><ESC> Mode REFRAPPE jusqu'à ce que l'utilisateur frappe <ESC>
s<texte><ESC> Remplace le caractère courant par le texte frappé jusqu'à <ESC>
3s<texte><ESC> Remplace 3 caractères par le texte frappé jusqu'à <ESC>
S<texte><ESC> Détruit la ligne courante et passe en mode INSERTION
~ Modifie le caractère courant (MAJUSCULE/minuscule)

Changement de mots
cw<texte><ESC> Remplace le mot par "texte".
Le mot à remplacer est délimité par $
c3w<texte><ESC> Remplace les 3 mots par "texte"
C ou c$ Remplace jusqu'à la fin de la ligne
c/chaîne Remplace jusqu'à chaîne non comprise

13.1.12 Annulation ou répétition d'une commande

Annulation d'une commande


u Annule l'effet de la dernière directive de
changement (même pour elle)
U Annule tous les changements effectués dans la
ligne courante
Répétition d'une commande
. (point) Effectue à nouveau la dernière commande de
modification de texte
Etat du fichier
^G ou Donne le nom, l'état du fichier, le numéro de
:f ligne, où est le curseur et le pourcentage de texte
au-dessus du curseur.

PS/LANGAGES Page 102


Annexes

13.1.13 Copie et déplacement de texte


Copie de texte
La directive y (yank) copie sans détruire l'objet dans un buffer sans nom.
y3w met les 3 mots suivants dans le buffer
Y ou yy met la ligne courante dans le buffer
5yy met 5 lignes dans le buffer

Il suffit de se positionner et de récupérer le contenu du buffer sans nom par les


directives p ou P
p Copie la dernière copie après l'objet du même type
P Idem avant l'objet du même type

Autres moyens pour copier du texte:


:5,8t25 les lignes 5 à 8 sont copiées après la ligne 25
:5,8co25 idem

Déplacement de texte
Pour chaque directive x ou d , VI mémorise la partie détruite dans un buffer sans nom
jusqu'à la prochaine destruction
Il suffit de se positionner et de récupérer le contenu du buffer sans nom par les
directives p ou P
p Copie la dernière copie après l'objet du même type
P Idem avant l'objet du même type

Autre moyen pour déplacer du texte:


:5,8m25 les lignes 5 à 8 sont déplacées après la ligne 25

13.1.14 Insérer le contenu d'un autre fichier


La directive :r permet l'insertion d'un autre fichier dans le buffer
:r fic le contenu de fic est inséré à l'emplacement du curseur

13.1.15 Insérer le résultat d'une commande dans un fichier


:r! commande permet d'insérer le résultat de la commande à partir de la position
courante du curseur

13.1.16 Copie d'une partie d'un fichier dans un autre fichier


:adresse1,adresse2w fichier.tmp
copie le texte compris entre les lignes adresse1 et adresse2 dans "fichier.tmp"
:/chaîne1/,/chaîne2/w fichier2
copie les lignes comprises entre chaîne1 et chaîne2 dans "fichier2"

13.1.17 Les buffers nommés (de la forme "lettre)


"a5yy met 5 lignes dans le buffer a
"f3yy met 3 lignes dans le buffer f
"ap insère le contenu du buffer a après le curseur

PS/LANGAGES Page 103


Annexes

13.1.18 Regroupement de lignes


J permet de regrouper des lignes (supprime le caractère fin de ligne de
la
ligne courante)

13.1.19 Echange de buffers nommés entre fichiers


:w sauvegarde du fichier courant
"b5yy mémorisation de 5 lignes dans le buffer nommé b
:e fic.nou édition d'un nouveau fichier
"bp copie des 5 lignes du buffer nommé b après la ligne courante
:e# retour au fichier de départ (ou <CTRL>A)

13.1.20 Récupération des objets détruits


L'éditeur sauvegarde les 9 derniers blocs de texte supprimés dans un jeu de registre
numérotés de 1 à 9
"1p récupération de la dernière destruction
". récupération de l'avant-dernière destruction
"3p récupération de la destruction qui précède l'avant-dernière

13.1.21 Recherche et remplacement de chaînes de caractères


Substitution de la 1ère occurrence de "chaîne1" par "chaîne2" pour les lignes d'adresse1
à adresse2
:[adresse1[,adresse2]]s/chaîne1/chaîne2/[options]

Substitution de la 1ère occurrence de "chaîne1" par "chaîne2" pour la ligne courante


:/chaîne1/s//chaîne2/ ou :/chaîne1/s/chaîne1/chaîne2/

Substitution de toutes les occurrences de "chaîne1" par "chaîne2" pour la ligne courante
:/chaîne1/s//chaîne2/g

Substitution de toutes les occurrences de "chaîne1" par "chaîne2" pour la ligne courante
avec demande de confirmation (y/n)
:/chaîne1/s//chaîne2/gc

Substitution de toutes les occurrences de "chaîne1" par "chaîne2" pour tout le fichier
:g/chaîne1/s//chaîne2/g

Substitution de toutes les occurrences de "chaîne1" par "chaîne2" pour tout le fichier
avec demande de confirmation
:g/chaîne1/s//chaîne2/gc

Substitution de toutes les occurrences de "chaîne1" par "chaîne2" pour tout le fichier
avec affichage des lignes traitées
:g/chaîne/s//chaîne2/gp

Substitution de toutes les occurrences de "chaîne1" par "chaîne2" sur toutes les lignes
ne contenant pas "chaîne3"
:v/chaîne3/s/chaîne1/chaîne2/g

PS/LANGAGES Page 104


Annexes

13.2 Table ASCII

D H Ctrl Mmen D H Ctrl Mmen


0 00 ^ NUL 16 10 ^P DLE
1 01 ^A SOH 17 11 ^Q DC1
2 02 ^B STX 18 12 ^R DC2
3 03 ^C ETX 19 13 ^S DC3
4 04 ^D EOT 20 14 ^T DC4
5 05 ^E ENQ 21 15 ^U NAK
6 06 ^F ACK 22 16 ^V SYN
7 07 ^G BEL 23 17 ^W ETB
8 08 ^H BS 24 18 ^X CAN
9 09 ^I HT 25 19 ^Y EM
10 0A ^J LF 26 1A ^Z SUB
11 0B ^K VT 27 1B ^[ ESC
12 0C ^L FF 28 1C ^\ FS
13 0D ^M CR 29 1D ^] GS
14 0E ^N SO 30 1E ^^ RS
15 0F ^O SI 31 1F ^_ US

D H Ch D H Ch D H Ch D H Ch D H Ch D H Ch D H Ch
32 20 SP 64 40 @ 96 60 ` 128 80 Ç 160 A0 á 192 C0 └ 224 E0 α
33 21 ! 65 41 A 97 61 a 129 81 ü 161 A1 í 193 C1 ┴ 225 E1 β
34 22 " 66 42 B 98 62 b 130 82 é 162 A2 ó 194 C2 ┬ 226 E2 τ
35 23 # 67 43 C 99 63 c 131 83 â 163 A3 ú 195 C3 ├ 227 E3 л
36 24 $ 68 44 D 100 64 d 132 84 ä 164 A4 ñ 196 C4 ─ 228 E4 ∑
37 25 % 69 45 E 101 65 e 133 85 à 165 A5 Ñ 197 C5 ┼ 229 E5 σ
38 26 & 70 46 F 102 66 f 134 86 å 166 A6 ª 198 C6 ╞ 230 E6 μ
39 27 ' 71 47 G 103 67 g 135 87 ç 167 A7 º 199 C7 ╟ 231 E7 τ
40 28 ( 72 48 H 104 68 h 136 88 ê 168 A8 ¿ 200 C8 ╚ 232 E8 φ
41 29 ) 73 49 I 105 69 i 137 89 ë 169 A9 ¬ 201 C9 ╔ 233 E9 Θ
42 2A * 74 4A J 106 6A j 138 8A è 170 AA ¬ 202 CA ╩ 234 EA Ω
43 2B + 75 4B K 107 6B k 139 8B ï 171 AB ½ 203 CB ╦ 235 EB δ
44 2C , 76 4C L 108 6C l 140 8C î 172 AC ¼ 204 CC ╠ 236 EC ∞
45 2D - 77 4D M 109 6D m 141 8D ì 173 AD ¡ 205 CD ═ 237 ED Ø
46 2E . 78 4E N 110 6E n 142 8E Ä 174 AE « 206 CE ╬ 238 EE ε
47 2F / 79 4F O 111 6F o 143 8F Å 175 AF » 207 CF ╧ 239 EF ∩
48 30 0 80 50 P 112 70 p 144 90 É 176 B0 ░ 208 D0 ╨ 240 F0 ≡
49 31 1 81 51 Q 113 71 q 145 91 æ 177 B1 ▒ 209 D1 ╤ 241 F1 ±
50 32 2 82 52 R 114 72 r 146 92 Æ 178 B2 ▓ 210 D2 ╥ 242 F2 ≤
51 33 3 83 53 S 115 73 s 147 93 ô 179 B3 │ 211 D3 ╙ 243 F3 ≥
52 34 4 84 54 T 116 74 t 148 94 ö 180 B4 ┤ 212 D4 ╘ 244 F4 ⌠
53 35 5 85 55 U 117 75 u 149 95 ò 181 B5 ╡ 213 D5 ╒ 245 F5 ⌡
54 36 6 86 56 V 118 76 v 150 96 û 182 B6 ╢ 214 D6 ╓ 246 F6 ÷
55 37 7 87 57 W 119 77 w 151 97 ù 183 B7 ╖ 215 D7 ╫ 247 F7 ≈
56 38 8 88 58 X 120 78 x 152 98 ÿ 184 B8 ╕ 216 D8 ╪ 248 F8 °
57 39 9 89 59 Y 121 79 y 153 99 Ö 185 B9 ╣ 217 D9 ┘ 249 F9 ·
58 3A : 90 5A Z 122 7A z 154 9A Ü 186 BA ║ 218 DA ┌ 250 FA ·
59 3B ; 91 5B [ 123 7B { 155 9B ¢ 187 BB ╗ 219 DB █ 251 FB √
60 3C < 92 5C \ 124 7C | 156 9C £ 188 BC ╝ 220 DC ▄ 252 FC ⁿ
61 3D = 93 5D ] 125 7D } 157 9D ¥ 189 BD ╜ 221 DD ▌ 253 FD ²
62 3E > 94 5E ^ 126 7E ~ 158 9E P 190 BE ╛ 222 DE ▐ 254 FE ■
63 3F ? 95 5F _ 127 7F 159 9F ƒ 191 BF ┐ 223 DF ▀ 255 FF

PS/LANGAGES Page 105


Table des matières

1. GENERALITES................................................................................................1
1.1 Introduction - Historique......................................................................................................................1

1.2 Notions de fonctions et de blocs...........................................................................................................2

1.3 Le compilateur c....................................................................................................................................4


1.3.1 La compilation sous UNIX.............................................................................................................5
1.3.2 La compilation sous TURBO C......................................................................................................5

2. ELEMENTS DE BASE DU LANGAGE............................................................6


2.1 Les identificateurs.................................................................................................................................6

2.2 Les mots réservés...................................................................................................................................6

2.3 Les séparateurs......................................................................................................................................7

2.4 Les commentaires..................................................................................................................................7

2.5 Principales directives de compilation..................................................................................................8


2.5.1 Généralités.......................................................................................................................................8
2.5.2 Inclusion de fichier..........................................................................................................................8
2.5.3 Définition de pseudo-constante.......................................................................................................8
2.5.4 Définition de macro-instructions....................................................................................................8
2.5.5 Compilations conditionnelles..........................................................................................................9

2.6 Les constantes......................................................................................................................................10


2.6.1 Les constantes entières..................................................................................................................10
2.6.2 Les constantes réelles....................................................................................................................10
2.6.3 Les constantes caractères..............................................................................................................10
2.6.4 Les constantes chaînes..................................................................................................................11

2.7 Les variables.........................................................................................................................................11

2.8 Structure d'un programme en langage C.........................................................................................13

3. LES TYPES DE BASE...................................................................................14


3.1 Généralités-classification....................................................................................................................14
3.1.1 Les types de base...........................................................................................................................14
3.1.2 Les types dérivés...........................................................................................................................14
3.1.3 Le type void...................................................................................................................................14
3.1.4 Les définitions de types par typedef.............................................................................................15

3.2 Les types entiers...................................................................................................................................15

3.3 Les réels................................................................................................................................................16

3.4 Les caractères......................................................................................................................................16

3.5 Initialisation des variables..................................................................................................................16

3.6 Modèle mémoire d'un programme C................................................................................................17

3.7 Classes d'allocation mémoire.............................................................................................................17


3.7.1 Les variables externes...................................................................................................................18
3.7.2 Les variables locales......................................................................................................................19
3.7.3 Les variables locales registres.......................................................................................................19
3.7.4 Tableau récapitulatif......................................................................................................................19

PS/LANGAGES Page 106


Table des matières
3.7.5 Définition et déclaration d'une variable........................................................................................20

3.8 Conversions de types...........................................................................................................................20


3.8.1 Combinaisons d'opérandes............................................................................................................20
3.8.2 Conversions lors d'assignations.....................................................................................................20
3.8.3 Casting d'opérandes.......................................................................................................................21

4. LES OPERATEURS DE BASE......................................................................22


4.1 Les opérateurs arithmétiques.............................................................................................................22

4.2 Les opérateurs de manipulations internes........................................................................................22

4.3 L'opérateur d'affectation....................................................................................................................22

4.4 Combinaison d'opérateurs..................................................................................................................23

4.5 Incrémentation / Décrémentation......................................................................................................23

4.6 Les opérateurs relationnels................................................................................................................23

4.7 Les opérateurs logiques......................................................................................................................23

4.8 Opérateur ternaire ou opérateur conditionnel................................................................................24

4.9 Opérateur séquentiel...........................................................................................................................24

4.10 Opérateurs d'adressage....................................................................................................................24

4.11 L'opérateur sizeof..............................................................................................................................24

4.12 Autres opérateurs..............................................................................................................................25

4.13 Priorités des opérateurs....................................................................................................................25

4.14 Remarques sur les règles de précédence.........................................................................................26

5. LES ENTREES - SORTIES SUR LES VOIES STANDARDS.......................27


5.1 Généralites ..........................................................................................................................................27

5.2 Les sorties mises en forme..................................................................................................................27

5.3 Les entrées mises en forme.................................................................................................................31

5.4 Les fonctions d'entrées-sorties de caractères...................................................................................34

5.5 Séquences de contrôle ansi.................................................................................................................36

6. LES INSTRUCTIONS EN C...........................................................................37


6.1 L'instruction if-else.............................................................................................................................37

6.2 L'instruction d'aiguillage switch........................................................................................................38

6.3 La boucle while....................................................................................................................................39

6.4 La boucle for........................................................................................................................................39

6.5 La boucle do...while.............................................................................................................................40

PS/LANGAGES Page 107


Table des matières
6.6 Les instructions break et continue (sauts associées aux boucles)...................................................40

6.7 L'instruction return............................................................................................................................41

6.8 L'instruction goto................................................................................................................................41

7. LES FONCTIONS...........................................................................................42
7.1 Définition de fonction..........................................................................................................................42

7.2 Appel d'une fonction...........................................................................................................................43

7.3 Passage de paramètres........................................................................................................................43

7.4 Retour du résultat...............................................................................................................................44

7.5 Prototypes des fonctions.....................................................................................................................44

7.6 Exemples...............................................................................................................................................45

8. LES TABLEAUX ET LES POINTEURS........................................................47


8.1 Les tableaux à un indice......................................................................................................................47
8.1.1 Initialisation d'un tableau à un indice...........................................................................................47

8.2 Les tableaux multidimensionnels.......................................................................................................48


8.2.1 Initialisation d'un tableau multidimensionnel...............................................................................48

8.3 Les chaînes de caractères...................................................................................................................49


8.3.1 Fonctions de traitement sur les chaînes de caractères..................................................................49

8.4 Tableaux et Fonctions.........................................................................................................................52

8.5 Les pointeurs........................................................................................................................................53


8.5.1 Généralités.....................................................................................................................................53
8.5.2 Déclaration - Utilisation................................................................................................................53
8.5.3 Pointeurs constants et pointeurs de constantes.............................................................................54
8.5.4 Arithmétique des pointeurs...........................................................................................................54
8.5.5 L'allocation dynamique dans le tas...............................................................................................54
8.5.6 Les pointeurs génériques...............................................................................................................55
8.5.7 Les pointeurs de fonction..............................................................................................................56
8.5.8 Les pointeurs et les arguments de fonction..................................................................................56
8.5.9 Les pointeurs et les opérations sur les tableaux............................................................................58
8.5.10 Les pointeurs et les chaînes de caractères..................................................................................59
8.5.11 Les tableaux de pointeurs............................................................................................................59
8.5.12 Les paramètres du programme principal....................................................................................60

9. LES TYPES ENUMERES ET STRUCTURES...............................................61


9.1 Les énumérations.................................................................................................................................61

9.2 Les structures.......................................................................................................................................62


9.2.1 Généralités - Déclaration...............................................................................................................62
9.2.2 Initialisation des structures............................................................................................................63
9.2.3 Accès aux éléments.......................................................................................................................63
9.2.4 Structures et Fonctions..................................................................................................................63
9.2.5 Pointeurs sur une structure............................................................................................................65
9.2.6 Structures récursives......................................................................................................................65

9.3 Les unions.............................................................................................................................................66

PS/LANGAGES Page 108


Table des matières
9.4 Les champs de bits...............................................................................................................................67

9.5 typedef...................................................................................................................................................68

10. LES FICHIERS.............................................................................................69


10.1 Généralités.........................................................................................................................................69

10.2 Les fonctions de gestion de fichier...................................................................................................69

10.3 Les fonctions de niveau 1..................................................................................................................70


10.3.1 open (fcntl.h)...............................................................................................................................70
10.3.2 eof (fcntl.h)..................................................................................................................................70
10.3.3 read .............................................................................................................................................71
10.3.4 write.............................................................................................................................................71
10.3.5 close (fcntl.h)...............................................................................................................................71
10.3.6 lseek (fcntl.h)...............................................................................................................................71

10.4 Les fonctions de niveau 2..................................................................................................................72


10.4.1 fopen (stdio.h)..............................................................................................................................72
10.4.2 fclose (stdio.h).............................................................................................................................72
10.4.3 fseek (stdio.h)..............................................................................................................................73
10.4.4 rewind (stdio.h)............................................................................................................................73
10.4.5 ftell (stdio.h)................................................................................................................................73
10.4.6 feof (stdio.h)................................................................................................................................73
10.4.7 ferror (stdio.h)..............................................................................................................................74
10.4.8 clearerr (stdio.h)..........................................................................................................................74
10.4.9 perror (stdio.h).............................................................................................................................74
10.4.10 getw (stdio.h).............................................................................................................................74
10.4.11 putw (stdio.h).............................................................................................................................74
10.4.12 fflush (stdio.h)...........................................................................................................................74
10.4.13 fwrite (stdio.h)...........................................................................................................................75
10.4.14 fread (stdio.h)............................................................................................................................75
10.4.15 Autres fonctions de lecture-écriture..........................................................................................75
10.4.16 Autres opérations sur les fichiers..............................................................................................75

11. AUTRES FONCTIONS DE LA BIBLIOTHEQUE STANDARD...................77


11.1 Les tests de catégories de caractères : <ctype.h>...........................................................................77

11.2 Les fonctions mathématiques : <math.h>.......................................................................................78

11.3 Les fonctions utilitaires : <stdlib.h>................................................................................................79

11.4 Les listes variables d'arguments : <stdarg.h>................................................................................80

11.5 Les fonctions de traitement de la date et de l'heure : <time.h>...................................................81

11.6 Les limites définies par l'implémentation : limits.h, values.h et float.h......................................82

11.7 Le fichier errno.h..............................................................................................................................84

11.8 Les fonctions, constantes et types de la bibliothèque conio.h.......................................................85

12. UTILITAIRES................................................................................................91
12.1 Gestion de projets..............................................................................................................................91
12.1.1 Make............................................................................................................................................91
12.1.2 Gestion de projets sous TURBO C.............................................................................................93

12.2 L'utilitaire LINT...............................................................................................................................93

PS/LANGAGES Page 109


Table des matières
12.3 Débogage des programmes sous UNIX...........................................................................................94
12.3.1 Utilisation de DBX......................................................................................................................94
12.3.2 Lancement et sortie.....................................................................................................................94
12.3.3 Pose de points d'arrêts.................................................................................................................95
12.3.4 Principales commandes d'édition................................................................................................95
12.3.5 Edition du source en cours de debug..........................................................................................95
12.3.6 Examen des variables du programme.........................................................................................95
12.3.7 Commandes diverses...................................................................................................................95

12.4 Débogage des programmes sous TURBO C...................................................................................96


12.4.1 Principales commandes...............................................................................................................96
12.4.2 Actions sur les variables..............................................................................................................96
12.4.3 Points d'arrêts...............................................................................................................................96

12.5 Gestionnaires de bibliothèques........................................................................................................96


12.5.1 L'utilitaire ar (UNIX)..................................................................................................................97
12.5.2 L'utilitaire TLIB (TURBO C).....................................................................................................97

13. ANNEXES.....................................................................................................98
13.1 UTILISATION DE VI.......................................................................................................................98
13.1.1 Présentation de VI.......................................................................................................................98
13.1.2 Spécification du type de terminal...............................................................................................98
13.1.3 Configuration de VI.....................................................................................................................98
13.1.4 Entrée dans VI.............................................................................................................................98
13.1.5 Sortie de VI..................................................................................................................................99
13.1.6 Création et insertion de texte......................................................................................................99
13.1.7 Déplacement du curseur dans un fichier...................................................................................100
13.1.8 Déplacement du curseur dans la fenêtre...................................................................................101
13.1.9 Recherche de chaînes de caractères..........................................................................................101
13.1.10 Destruction de texte.................................................................................................................101
13.1.11 Remplacement de texte...........................................................................................................102
13.1.12 Annulation ou répétition d'une commande.............................................................................102
13.1.13 Copie et déplacement de texte................................................................................................103
13.1.14 Insérer le contenu d'un autre fichier.......................................................................................103
13.1.15 Insérer le résultat d'une commande dans un fichier...............................................................103
13.1.16 Copie d'une partie d'un fichier dans un autre fichier..............................................................103
13.1.17 Les buffers nommés (de la forme "lettre)...............................................................................103
13.1.18 Regroupement de lignes..........................................................................................................104
13.1.19 Echange de buffers nommés entre fichiers.............................................................................104
13.1.20 Récupération des objets détruits.............................................................................................104
13.1.21 Recherche et remplacement de chaînes de caractères............................................................104

13.2 Table ASCII.....................................................................................................................................105

PS/LANGAGES Page 110