Introduction au Langage C et Ses Concepts
Introduction au Langage C et Ses Concepts
SOMMAIRE
.1 Généralités .......................................................................................................................... 2
.2 types de base....................................................................................................................... 3
.3 Instructions ......................................................................................................................... 4
.3.1 Affectation / Expressions ........................................................................................... 4
.3.2 Instructions de sélection ............................................................................................. 6
.3.3 Instructions de répétition ............................................................................................ 7
.3.4 Autres instructions...................................................................................................... 8
.4 Entrées – Sorties bufférisées ............................................................................................ 10
.4.1 Entrées-Sorties non formatées .................................................................................. 10
.4.2 Entrées-Sorties formatées ......................................................................................... 10
.5 Déclaration – Allocation mémoire ................................................................................... 13
.5.1 Classes d’allocation .................................................................................................. 13
.5.1.1 Variables extérieures aux fonctions ................................................................. 13
.5.1.2 Variables déclarées dans une fonction ............................................................. 13
.5.1.3 Déclaration de fonctions................................................................................... 14
.5.1.4 Classe d’allocation registre .............................................................................. 14
.5.2 Les objets structurés ................................................................................................. 14
.5.2.1 Tableaux ........................................................................................................... 14
.5.2.2 Les structures .................................................................................................... 15
.5.2.3 Les unions ........................................................................................................ 15
.5.2.4 Définition de type (création de synonymes) .................................................... 16
.5.2.5 Les énumérations.............................................................................................. 16
.5.2.6 Les pointeurs .................................................................................................... 16
.6 Conversion de types : coercion ........................................................................................ 18
.7 Allocation dynamique de zones ....................................................................................... 18
.8 Les fonctions .................................................................................................................... 19
.8.1 Définition ................................................................................................................. 19
.8.2 Fonctions récursives ................................................................................................. 20
.8.3 Les pointeurs sur les fonctions ................................................................................. 20
.8.3.1 Affectation de fonctions ................................................................................... 20
.8.3.2 Tableau de fonctions ........................................................................................ 21
.8.3.3 Passage de fonctions en arguments de fonctions ............................................. 21
.9 Récupération des arguments d'une commande................................................................. 21
.10 La compilation.............................................................................................................. 22
.10.1 Compilation et edition de liens sous UNIX ............................................................. 22
.10.2 Le pré-compilateur C ............................................................................................... 23
.10.2.1 Inclusion de fichiers ......................................................................................... 23
.10.2.2 Macro – definition ............................................................................................ 23
.10.2.3 Compilation conditionnelle .............................................................................. 24
.11 Manipulation de Fichiers .............................................................................................. 26
.11.1 Ouverture/Fermeture d’un fichier ............................................................................ 26
.11.2 Lecture/Ecriture octet par octet ................................................................................ 27
.11.3 Déplacement du pointeur ......................................................................................... 28
.11.4 Lecture/Ecriture d’objets quelconques ..................................................................... 29
.11.5 Lectures/Ecritures formatées .................................................................................... 29
.11.6 Lectures/Ecritures de chaînes de caractères ............................................................. 30
.11.7 Compléments sur le paramètre mode passé à fopen ................................................ 30
LE LANGAGE C
.1 Généralités
Le caractéristiques sont :
Langage structuré : pas de goto, typé c’est-à-dire déclaration
obligatoire (mais laxisme au niveau de la vérification.
Langage d’un niveau moyen
Langage permettant la manipulation d’objets très élémentaires
proche de l’architecture des processus :
- décalage de chaînes de bits
- accès aux registres
Exemple de programme en C
bonjour.c
#include<stdio.h>
void main()
{
printf("Bonjour les amis");
}
#if
#else
#endif - compilation conditionnelle
#ifdef
#ifndef
.2 types de base
- caractères : char
exemple : char c ; ‘a’ notation
les caractères particuliers : ‘\n’ newline, ‘\t’ tab, ‘\0’ NULL, ‘\\’ \, ‘\b’
backspace, ‘\r’ return, ‘\f’ formfeed ou clear screen, ‘\’’ ‘, ‘\"’ ".
int x ; char c ;
c = ’a’ +1 ; /* c ’b’ */
x = c; /* x 66 */
c = x+2; /* c ‘d’ */
Définition de constantes
#define PI 3.14
#define EOL ‘\n’
#define ERR1 "Code inconnu \n"
.3 Instructions
Opérateurs d’affectation
= opérateur d’affectation
Exemple : i = 2*j+3 ;
= affectation multiple
Exemple: i=7+ (j=3);
f=g=h=9;
incrémentation / décrémentation
exemple:
i = 2;
j = 2*i++;
k = 2*++i;
Opérateurs logiques
= = égalité
Exemple : if (x==0)
!= non égal
Exemple : (x !=y)
! négation
&& Et logique
|| Ou logique
autres
expression simple
Expression quelconque suivie de ; i++; x=*++p;
expression composée
{ [déclarations locales]
suite d'instructions }
exemple:
{ int aux;
aux = i;
i = j;
j = aux;
} obligatoire (;)
pas de ;
Sélection if:
if (<expression>)
<instruction>
[ else <instruction>]
if (delta>0)
{ … } pas de ;
else if (delta = = 0)
x = -b/(2*a);
else printf (" pas de raciness réelles\n");
Sélection switch
switch (<expression>)
{case <expression constante>: <liste d'instructions>
…
[default : <liste d'instructions>]
}
char c;
switch (c)
{ case 'd' :
case 'c' : supprimer( ); break;
case 'i' : inserer( ); break;
case 'm' : modifier ( );break;
case 's' : sortir( ); break;
default : printf ("erreur code\n");
}
répétition do while:
do
<instruction>
while (<expression>);
do
i--;
while(i);
répétition for:
for (<liste1>; <expression>; <liste2>) <instruction>;
exemples:
for (;;) boucle infinie
for(i=0; i<=n; i++)
for (i=0; i<=n; i++, j--)
for (l1;e;l2) <instruction> while (e) {<instruction> l2}
sortie break
permet une sortie immédiate de l'instruction for, while, do while ou switch
englobante.
Exemple:
sortie exit(n)
termine l'exécution du programme et renvoie n au processus père
(0 n 255) après fermeture de tous les fichiers.
(exit(0) implicite en fin de programme)
continue
passe à l'itération suivante d'un for, while ou do while (peu utilisé).
+ = == ! ~ & ?:
- += != || >> * ,
* -= < && << [] sizeof
/ *= <= & . ( type )
% /= > | ()
++ %= >= ^
-- >>=
<<=
&=
^=
|=
puts(buff):
- buff doit être un pointeur sur une chaîne de caractère (se terminant par
'\0')
- puts écrit cette chaîne sur stdout (non compris le caractère '\0') et ajoute
un '\n'.
règles:
- %c le caractère suivant;
- %i%f%s ignore tous les \t, \n, espace puis lit jusqu'à la rencontre d'un
- non numérique (%i%f)
- espace, \t, \n (%s)
- %* donnée ignorée
- %3d lit exactement un entier sur 2 caractères
- %1s lit le premier caractère non espace.
- scanf renvoie EOF si une erreur ou une fin de fichier est detectée au cours
de la lecture. EOF vaut en général –1.
- cadrage à gauche
n impression dans une zone de n caractères (cadrage à droite implicite)
.m m 1ers caractères d'une chaîne ou m décimales pour un float
n.m combinaison des deux précédents.
Ce sont des variables globales partagées par les fonctions qui ne les redéfinissent
pas et qui existent pendant toute la durée du programme.
La classe d’allocation des fonctions est la même que pour les variables
Exemple : main()
{ register int i,s ;
s = 0;
for (i = 1; i<=10000; i++) s = s +i;
printf(“%d \n”, s);}
Les variables automatiques (locales aux fonctions et non “static”) allouées dans
la pile en temps normal, et de type char, int, float ou "pointeur" peuvent être
déclarées register. Elles sont alors allouées si possible dans les registres
machine. Ce qui implique une diminution sensible du temps d'exécution
(réduction de moitié sur le type d'exemple).
.5.2.1 Tableaux
Exemples:
char t[10]; tableau de 10 caractères t[0] t[1] ... t[9]
int u[ ] = {6, 5, 7, 3};
taille facultative si initialisé
float mat[9][15];
mat[i][j] = 3.5;
union objet
{ float r;
char t[4];
int i;
int t[20];
int *p; /* *p est un entier, p est un pointeur sur un entier */
19
int t[20];
int *p = t;
char *s;
s = "abcd"; /* s pointe sur le début d'une constante chaîne */
que désigne s[3] et *(s+3)?
Tableaux de pointeurs
char * name[] = {"lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi",
"dimanche"};
name
|l|u|n|d|i|\0
0
*name[0]
name[0][0]
**name
*name[1]
**(name + 1)
name[1][0]
*(name[0] + 1)
*(*name + 1)
name[0][1]
int *p;
char *q;
q = (char *)p;
p = (int *)q;
i = (int)p;
p = (int *)i;
i = (int)pf;
pf = ((int*)())i;
Sert à réserver une zone mémoire pour les variables de type pointeur.
Exemple:
t = (int *)calloc(100, sizeof(int)); /* t tableau de 100 entiers = à 0 */
- q = realloc(p, t); réalloue la zone pointée par p dans une zone de taille t octets
pointée par q avec recopie (tronquée si la nouvelle zone est plus petite).
.8 Les fonctions
.8.1 Définition
Exemple:
void swap(int *x, int *y)
{ int aux;
aux = *x ;
*x = *y ;
*y = aux ;
}
a = 1;
b = 2;
swap (&a, &b); /* appel de la fonction */
Une fonction récursive est une fonction qui s'appelle elle-même dans sa
définition.
Exemple: la somme des valeurs d'un arbre étiqueté par des nombres entiers.
sigma(nœud *a)
{ if(a = = NULL) return (0); /* condition d'arrêt */
else return (ainfo + sigma(agauche) + sigma(adroit));
}
int f1(x) { … };
int f2(x) { … };
int f3(x) { … };
int(*pf)();
if (x = = 1)
pf = f1; /* affectation d'une fonction à pf */
else if (x = = 2)
pf = f2;
else pf=f3;
On aura : argc = 4
argv[0] = "prog"
argv[1] = "f1.c"
argv[2] = "-a"
argv[3] = "3"
argv[4] = NULL
car les arguments sont affectés au lancement du programme.
Exemple: Programme qui doit avoir au moins un argument autre que le nom du
programme et qui affiche ses arguments à l'écran.
.10 La compilation
cc f1.c f2.c
- compile f1 et f2
- engendre f1.o et f2.o
- engendre a.out qui est exécutable si f1 ou f2 contient main()
.10.2 Le pré-compilateur C
#include "f1"
#include "../d/h"
#include<stdio.h>
#include "/usr/include/stdio.h"
#define BEGIN {
#define END }
#define IF if(
#define THEN )
IF x = = 0 THEN if (x = = 0)
BEGIN {
x++; x++;
END }
exemple:
for (i = 0; i < n; i++) SWAP(t[i], t[i+1]);
devient
for (i = 0; i < n; i++) { int aux;
aux = t[i];
t[i] = t[i+1];
t[i+1] = aux;}
- Attention au parenthèse
#define k 100
ak=3; a100 = 3;
tous les k sont substitués
Exemples:
#ifdef DEBUG
printf("Appel de f()");
#endif
cc –DDEBUG …
#ifdef NUMELEC
#include "numelec.h"
#else /* version */
#include "standard.h"
#endif
/* pour éviter de redéfinir des macros pouvant être définies dans des fichiers
importés par #include */
#ifndef VRAI
#define VRAI 1
#define FAUX 0
#endif
L’ouverture d’un flux s’obtient à l’aide de la fonction fopen qui, entre autres
opérations, réserve un tampon mémoire et retourne un pointeur permettant
l’accès à ce tampon.
Syntaxe : pf = fopen(nom, mode) ;
nom est une chaîne de caractères désignant le nom externe du fichier : pour un
fichier disque c’est le nom du fichier sous DOS.
Exemple : a :monfich.txt
mode est aussi une chaîne de caractères, elle permet de préciser le mode
d’accès : lecture (r), écriture (w), ou ajout (a). Plusieurs options sont
possibles, pour plus de détails se reporter à la fin de ce chapitre.
pf est un pointeur sur une structure, notée FILE, prédéfinie dans stdio.h. Toutes
les manipulations ultérieures sur le fichier utiliseront ce pointeur.
Exemple :
la fonction fclose ferme le flux ouvert par fopen, vide le buffer et libère la
mémoire et le pointeur p associé au flux. Oublier de fermer un flux peut être très
dangereux !
Plusieurs flux sont ouverts par le système lui même, si bien que l’utilisateur peut
accéder directement aux périphériques correspondants, il s’agit de :
exemple :
Dans stdio.h les fonctions fopen rt fclose sont déclarées par les prototypes :
Les fonctions de lecture/écriture les plus simples travaillent octet par octet : ce
sont fgetc et fputc. Il existe également deux macroinstructions qui remplissent le
même rôle : getc et putc.
fgetc lit un octet dans le flux et renvoie l’octet pointé en cas de succès, EOF en
cas d’erreur. Le pointeur est automatiquement incrémenté.
Exemple :
char mot ;
FILE *pf ; / déclaration d’un pointeur sur un fichier */
fputc écrit un octet, passé à la fonction comme premier paramètre, dans le flux.
Exemple :
Comme fgetc, fputc retourne EOF en cas d’erreur, et sinon la valeur de l’octet
passé comme paramètre. putc est une macroinstruction qui réalise la même
opération.
Le pointeur obtenu par appel de fopen ne représente pas une adresse mémoire et
ne peut être manipulé directement: ++pf ou (pf+1) n’ont pas de sens. Il faut
appeler des fonctions spécifiques pour se déplacer dans le fichier (fseek, rewind)
ou obtenir des informations sur la position courante du pointeur (ftell, feof).
Exemple
fseek (pf, 3802L,0); /* le pointeur pf est amené à pointer sur le 3802 éme
octet, partant du début de fichier */
Le deuxième paramètre est un entier de type long et le troisième peut prendre les
valeurs 0, 1 ou 2 pour exprimer un déplacement depuis le début du fichier, la
position courante ou la fin respectivement.
- feof indique que le pointeur est en fin de fichier: cette fonction retourne la
valeur 0 dans ce cas.
Les fonctions fread et fwrite permettent de lire ou d’écrire des objets de taille
quelconque, taille exprimée en nombre d’octets.
Exemples d’utilisation :
fread(pt_obj, sizeof(int),n,pt_fich) ;
fwrite(pt_obj, sizeof(int),n,pt_fich);
Les octets lus ou écrits dans le fichier le sont en nombre compatible avec le type
(4 pour un float par exemple), et interprétés conformément à ce type.
Exemple :
Le premier paramètre passé à la fonction est un pointeur sur le fichier (ici stdprn
pour le port parallèle), les suivants sont identiques aux paramètres de printf ou
de scanf.
Exemple :
fgets(str, n, pt_fich) ;
La fonction fgets lit des caractères depuis le flux d’entrée pt_fich et les place
dans la chaîne str. La fonction cesse la lecture soit lorsque n-1 caractères ont été
lus, soit à la lecture d’un caractère d’interligne (‘\n’). fgets ne recopie pas le
caractère d’interligne dans str. Le dernier caractère lu est toujours suivi d’un
caractère nul (‘\0’) dans str.
La fonction fputs recopie dans le flux de sortie pt_fich la chaîne pointée par str
et terminée par un caractère nul, elle n’ajoute pas de caractère d’interligne.
fputs(str,pt_fich) ;
r+ : le fichier doit déjà exister, il n’est pas modifié par fopen.
w+ : le fichier est crée ou écrasé par fopen, ce mode n’est intéressant que pour
un nouveau fichier.