Langage de programmation 1. Concepts ... Comporte des exercices dont les
solutions sont publiées dans : “Exercices corrigés sur le langage C, solutions des
...
Langage de programmation 1 Concepts avancés du développement en C sous Unix
[email protected]
2
K&R “Le langage C, norme ANSI” Brian W. Kernighan, Denis M. Ritchie 2ème édition, 1988, Prentice-Hall / Dunod
© Dominique Lazure
Comporte des exercices dont les solutions sont publiées dans : “Exercices corrigés sur le langage C, solutions des exercices du Kernighan et Ritchie” C. Tondo, S. Gimpel, 2000.
3
Hello world ! /* File: hello.c Author: Dominique Lazure Creation date : Oct 4 2002 Last modification : Feb 1 2005 */
© Dominique Lazure
#include int main(void) { printf("Hello world !\n"); }
4
Commentaires /* un commentaire façon classique */ Pas d'imbrication : fin sur la prochaine séquence de fermeture // un autre commentaire (à la C++)
© Dominique Lazure
Fin en fin de ligne Du bon usage des commentaires : Entête pour chaque fichier Spécification des fonctions avant le corps d'une fonction Eviter les commentaires insignifiants ( i=i+1; /* incrémentation */ ) Prendre l'habitude de commenter en anglais
5
#include Inclut un fichier d'entêtes (généralement .h) à partir : de la bibliothèque du compilateur (dans /usr/include) #include du répertoire courant (utilisateur) #include “monprojet.h”
© Dominique Lazure
Permet au compilateur certaines vérifications de type Par défaut : un paramètre de fonction est entier Différence entre C-K&R et C-ANSI Warnings du compilateur, pas d'erreur de compilation
6
Pré-processeur cpp Consomme les directives : #include #define
© Dominique Lazure
#undef #ifdef ... #else ... #endif
inclut un fichier header définit une macro annule une macro si une macro est définie ou non définie (ne compile pas l'alternative)
#ifndef
7
#define Constantes, Macros : #define #define #define #define
FAUX 0 VRAI (!FAUX) PI 3.141529 UNE_LONGUE_MACRO { printf(“Hello “);\ printf(“World !\n”); }
© Dominique Lazure
Macros avec paramètre(s) : #define abs(x) ((x)B?A:B)
Attention à la priorité des opérateurs !
8
#define n'est pas fonction ! #define mdeuxfois(c) (2*c)
© Dominique Lazure
int fdeuxfois(int c) { return (2*c) ; } main() { int x=3,resuMacro,resuFonc; resuMacro=mdeuxfois(x+1); resuFonc=fdeuxfois(x+1); }
9
© Dominique Lazure
Compilation directe % cc hello.c -o hello % ls -l hello* -rwxr-xr-x 1 dushmol -rw-r--r-1 dushmol % make hello make: 'hello' is up to % touch hello.c % make hello cc hello.c -o hello % ls -l hello* -rwxr-xr-x 1 dushmol -rw-r--r-1 dushmol
linfo linfo
3455 Oct 4 11:47 hello 123 Oct 4 11:46 hello.c
date.
linfo linfo
3455 Oct 4 11:49 hello 123 Oct 4 11:47 hello.c
10
Phases de compilation
Editeur de texte % emacs hello.c
hello.c
hello
Exécution % hello Hello World !
© Dominique Lazure
Compilation % cc hello.c -o hello
Préprocesseur % man cpp
.c
Compilateur C % man gcc
Hello.o
printf.o
Édition de liens % man ld libc.a
11
Édition de liens Créer un binaire exécutable à partir des différents objets binaires et des librairies.
© Dominique Lazure
Exécutables linkés statiques : % gcc -static Le code des fonctions est inclu dans l'exécutable Cas de certaines librairies non libres (Motif) Exécutables plus volumineux Temps d'exécution réduit Exécutables linkés dynamiques (défaut) : % ldd hello Le code des fonctions est chargé lors des premiers appels Pas de recompilation lors de changement de librairie Exécutables plus légers
12
Édition de liens Créer un binaire exécutable à partir des différents objets binaires et des librairies.
© Dominique Lazure
Exécutables linkés statiques : % gcc -static %man gcc … -static On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect. This option will not work on Mac OS X unless all libraries (including libgcc.a) have also been compiled with -static. Since neither a static version of libSystem.dylib nor crt0.o are provided, this option is not useful to most people.
13
Appel d'un programme A partir d'un shell Entrée standard : Par défaut :
le clavier
Redirection à partir d'un fichier :
< filename
© Dominique Lazure
Sortie standard : Par défaut :
la fenêtre shell
Redirection dans un fichier : Écrasement du contenu initial : Concaténation :
> filemane >> filename
Redirection vers une commande :
| commande
Sortie erreur : Par défaut : Redirection avec écrasement : Redirection avec concaténation :
la fenêtre shell 2> filename 2>> filemane
14
Compilation séparée
© Dominique Lazure
Un gros projet se doit d'être découpé en plusieurs modules. Exemple : développement d'un navigateur web Gestion des protocoles : http.c http.h ftp.c ftp.h Gestion des URL : url.c url.h Gestion de l'affichage : texte.c texte.h images.c images.h Gestion des favoris : bookmark.c bookmark.h ... Programme principal : minifox.c #include #include “book.h” #include “url.h” Conséquences sur les déclarations de variables (cf plus tard)
15
© Dominique Lazure
Compilation en objets binaires % ls http.c http.h minifox.c url.c url.h % cc -c url.c % ls http.c http.h minifox.c url.c url.h url.o % cc -c http.c % cc -c minifox.c % ls http.c http.h http.o minifox.c minifox.o url.c url.h url.o % cc http.o url.o minifox.o -o minifox % ls -l minifox -rwxr-xr-x 1 dushmol linfo 12345 Oct 4 11:45 minifox
16
Gestionnaire de projet Unix : Makefile (1) Makefile :
fichier comportant une suite d'entrées, lu par % make
Entrée :
cible: dépendances action
Exemple : http.o: http.c http.h url.h cc -c http.c
© Dominique Lazure
url.o: url.c url.h cc -c url.c texte.o: texte.c texte.h cc-c texte.c minifox.o: minifox.c http.h url.h texte.h cc -c minifox.c minifox : minifox.o http.o texte.o url.o cc minifox.o http.o texte.o url.o -o minifox
17
Makefile (2) Commentaires : lignes commençant par # Gestion de macros (comme les variables de bash) (% make -p) CC=/usr/bin/cc CFLAGS=” -O -systype bsd43” Macros spéciales : $@ cible de la règle courante $? liste des dépendances changées © Dominique Lazure
$< nom du fichier qui a causé le déclenchement de l'action $* prefix commun à la cible et aux dépendances pretty: pretty.c $(CC) $(CFLAGS) $? -o $@
18
Makefile (3) Cible par défaut : première entrée Cible(s) en argument(s) de l'appel à make Règles sans dépendances : clean: -rm *.o
© Dominique Lazure
Règles par défaut : .o.c: $(CC)
*~
$(CFLAGS)
core
-c $*.c
Arrêt de la compilation à la première erreur (sauf -action) Echo en sortie standard des commandes lancées (sauf @action) Exécution de make sans déclenchement des actions : % make -n
19
Makefile (4) Exemple de construction d'une librairie : MYLIB=libmy.a
© Dominique Lazure
OBJETS=x.o y.o z.o AR=ar $(MYLIB): $(OBJETS) $(AR) rvu $@ $(OBJETS) ; ranlib $@
20
Makefile (5) Les gros projets sont gérés avec des arborescences de sources Exemple :
© Dominique Lazure
MYTOOLDIR=../mesoutils MYLIB=$(MYTOOLDIR)/libmy.a $(MYLIB): cd $(MYTOOLDIR) make libmy.a
Erreur ! make forke un shell par ligne d'action(s) déclenchée. Continuation de ligne : \ Make and Makefiles, Reg Quinton, University of Ontario. http://ist.uwaterlo.ca/~reggers
21
Hello world ! /* File: hello.c Author: Dominique Lazure Creation date : Oct 4 2002 Last modification : Feb 1 2005 */
© Dominique Lazure
#include int main(void) { printf("Hello world !\n"); }
22
Fonctions Toute instruction C fait partie d'une fonction Toute fonction comporte : Une entête – header (de préférence commentée)
© Dominique Lazure
Un type pour la valeur de retour (éventuellement void) Un nom de fonction (identifiant) Une liste (vide) de paramètres formels
Un corps - body Liste d'instructions entre { } séparées par ;
23
Interaction shell / programme C
Fonction appelée au lancement du processus : int main()
© Dominique Lazure
Code de retour renvoyé à l'appelant : Entier $? de bash (par convention : 0 = succès) section 'RETURN VALUE' des pages man.
24
Appel d'une fonction nom ( paramètres_liste )
© Dominique Lazure
Liste des paramètres effectifs : Séparés par des , Eventuellement vide (void) Passage des paramètres par valeur Evaluation des paramètres dans un ordre quelconque
25
printf Affiche sur la sortie standard une chaine de caractères int printf( char * format,...);
Retour : nombre de caractères affichés (sauf \0)
© Dominique Lazure
Autres arguments : référencés (et typés) dans le premier argument %d %u %x %c %s %f
entier entier non signé entier en hexadécimal caractère chaine de caractères nombre réel
26
Représentation interne/externe
© Dominique Lazure
printf (“%c %d %x”,65,65,65); Aucune vérification effectuée (impossibilité) Segmentation faut, core dumped Possibilités diverses pour le format % man 3 printf Caractères spéciaux pour printf : \\ \n \f \r
\ newline form-feed carriage return \v
\a bell \b backspace \t tabulation H tabulation V
27
Mon second programme
© Dominique Lazure
#include main() { int i=1; while ( i < . ++ -- + * & (type) sizeof % >
>=
-=
*=
/=
%=
&=
^=
|=
=
56
© Dominique Lazure
Quelques expressions à éviter ! a+++b ; a+ ++b; a[i]=i++ a[i]=a[i++] a=+3 a=xy ; a=xy; a != a&1 ; a=1,2; a=(1,2); a=f(n,n++); x&&y; x&(&y); ...
57
Opérations bit à bit : masquage Déclaration de variable : un octet minimum. Idée : stocker 8 informations booléennes par octet.
© Dominique Lazure
Principe : déclarer un masque (puissance de 2) par booléen. #define m_read 4 #define m_write 2 #define m_exec 1 Affectation masquée : Positionnement à 1 : Inversion : Positionnement à 0 :
variable |= mask ; variable ^= mask ; variable &= ~mask ;
Isolement du masque :
(variable & mask ) ?...
58
Isolement d'une tranche (K&R) #define entier #define byte
unsigned int unsigned char
entier lirebits (entier x, byte p, byte n) { return ( (x>>(p-n+1)) & (~((~0) argum.c Longueur théorique non bornée Usage conventionnel : marqueur de fin de chaîne : Les bibliothèques simplifient l'usage.
'\0'
71
Les erreurs classiques Erreur d'allocation : dépassement Prévoir suffisamment de place, contrôler ! Erreur d'affectation : toto=Nom ;
Copie impérative élément par élément
© Dominique Lazure
Erreur de longueur : lg=sizeof(toto);
Parcours de la chaîne par une boucle jusqu'à '\0' Utilisation de strlen() Bibliothèques de fonctions : strlen, strcpy, strcat, strcmp, strncpy...
72
Pointeurs génériques : void* Certaines fonctions ne connaissent pas le type pointé Exemple : #include void bcopy (const void *src, void *dest, size_t n);
© Dominique Lazure
size_t est le type de retour de l'opérateur sizeof Utilisés comme des pointeurs de caractères : int SRC[10],DEST[10]; bcopy (SRC,DEST,10*sizeof(int)); Un pointeur sur void doit être converti avant tout déréférencement
73
Arithmétique des pointeurs Les opérateurs classiques s'appliquent naturellement aux pointeurs Addition ou soustraction d'un pointeur et d'un entier Incrémentation / décrémentation de pointeur Comparaison de deux pointeurs homogènes Affectation, comparaison à NULL
© Dominique Lazure
Unité de mesure : la taille (en octets) de l'élément pointé.
74
Arithmétique des pointeurs
© Dominique Lazure
int TAB[10]={1,2,3,4,5,6,7,8,9,10},i; int *PI=TAB; char *PC=TAB; for (i=0;i nécessite un pointeur non nul ! Segmentation fault. Core dumped
79
Union (types discriminés) Ensemble de champs non tous alloués Accès indépendants à tous les champs. sizeof (union) = Maxchamps (sizeof(champs))
© Dominique Lazure
Syntaxe identique à celle des structures : union info { struct judoka DD; struct pongiste SP; }; struct adherent { unsigned int carte; enum discipline sport; union info ref; };
/* discriminent */
struct adherent toto={1234,JUDO}; toto.ref.DD.ceinture=NOIRE; toto.ref.SP.classement=15;
80
Champs de bits (bitslice) Économiser sur le format de stockage des types entiers. Intervalle de valeurs possibles identifié, énuméré. Taille explicitement précisée pour un champ (en nombre de bits) struct droits { unsigned char owner:3; unsigned char group:3; unsigned char others:3; };
© Dominique Lazure
struct droits fic; fic.owner=REA|WRI|XEQ; fic.group=REA|XEQ; fic.others=0; Pas de vérification de débordement ! Interdiction d'utiliser l'opérateur & (ce ne sont pas des tableaux)
81
Synonyme de types : typedef Permet de raccourcir les écritures. Exemples : typedef struct toto titi; struct toto t1; titi t2; typedef union toto titi; union toto t1; titi t2;
© Dominique Lazure
typedef enum toto titi; enum toto t1; titi t2; typedef int titi[100]; int t1[100]; titi t2; typedef char * str; char *msg1; str msg2;
82
Types récursifs : la liste chaînée struct maillon { objet obj; struct maillon * suivant; };
© Dominique Lazure
typedef struct maillon maillon, * liste; liste l; maillon m1,m2; objet o; m1
l=&m1; m1.obj=o; (*l).obj=o; (*l).suivant=&m2; l->obj=o; l->suivant=&m2;
obj
suivant
m2 l
83
© Dominique Lazure
Questions / Remarques
Le passage de paramètres
[email protected]
85
Principe général
© Dominique Lazure
Passage par valeur : 1. 2. 3. 4. 5. 6. 7. 8.
Évaluation des paramètres effectifs Copie des résultats sur la pile Appel de la fonction Association des paramètres formels Exécution de la fonction Évaluation du résultat (return) et dépilement Retour à la fonction appelante Récupération du résultat en sommet de pile
86
Exemple int addition(int a, int b) { int c; c=a+b; return c; } foo() { int x=12,y=45,z; z=addition(x,y); © Dominique Lazure
}
87
''Contre''-exemple void incrementer(int a) { a=a+1; }
void incrementer(int *a) { *a=*a+1; }
foo() {
foo() { int x=12; incrementer(x);
© Dominique Lazure
}
int x=12; incrementer(&x); }
88
Tableau en paramètre Nom d'un tableau (sans crochet) : adresse de base.
© Dominique Lazure
void bar(int T[], int lg) { int i; for (i=0;i