C2 - Langage C - ISIMA 1 - Deuxieme partie

203
http://www.isima.fr/~loic tembre 2016 – Version étudiante 1

Transcript of C2 - Langage C - ISIMA 1 - Deuxieme partie

Page 1: C2 - Langage C - ISIMA 1 - Deuxieme partie

http://www.isima.fr/~loic

Septembre 2016 – Version étudiante

1

Page 2: C2 - Langage C - ISIMA 1 - Deuxieme partie

2

Être un ingénieur ?• Présence en cours• Présence active en TP

Présence contrôlée Préparer les TPs

• Pas de document aux examens Entretiens Culture générale

• Savoir se documenter• Rendre des TPs à l'image du travail

Guide de style & Génie Logiciel & Commentaires Tests Honnêteté (faute professionnelle)

Page 3: C2 - Langage C - ISIMA 1 - Deuxieme partie

Pré-requis :• Initiation algo• Initiation C/UNIX

3

Plan

• Outillage & méthodes

• Compilation séparée / Makefile

• Révisions• Pointeurs

de variable de fonction

• Structures• Macros

• Fichiers binaires• Ligne de

commande• Système• Arguments var• SDL

5

12

41

48, 105185

84, 168

144

150

194

179

204

119

Page 4: C2 - Langage C - ISIMA 1 - Deuxieme partie

OUTILLAGE & MÉTHODES

Page 5: C2 - Langage C - ISIMA 1 - Deuxieme partie

Un logiciel

• Utilisateurs ? Besoins Spécifications

• Développeurs Analyse // Algorithmique Développement Tests Maintenance / Evolutions

5

Page 6: C2 - Langage C - ISIMA 1 - Deuxieme partie

6

Compilateur• ISIMA

gcc [ etud ]

• À la maison : gcc sous une distribution LINUX gcc sous Cygwin gcc sous MinGW / CodeBlocks

• Visual Studio ? C'est du C++

• Bon éditeur ou EDI

NORMES :• ANSI C• ISO C 90

Page 7: C2 - Langage C - ISIMA 1 - Deuxieme partie

Débogueur

• Recherche de bogues à l'exécution Analyse d'un programme en temps réel Point d'arrêt Exécution pas à pas Inspection des variables

• GDB // DDD

7

$ gcc -g En annexe

Page 8: C2 - Langage C - ISIMA 1 - Deuxieme partie

Profileur

• Analyse de l'exécution• Occupation mémoire

Eviter les fuites mémoires• Temps d'exécution

Optimisation• Gprof // valgrind

8

$ gcc -g

Page 9: C2 - Langage C - ISIMA 1 - Deuxieme partie

Gestionnaire de versions

• Développement à plusieurs Diffusion du code Gestion des conflits

• Historique Régression ? Retour en arrière ? Fonctionnalités à venir

9

Page 10: C2 - Langage C - ISIMA 1 - Deuxieme partie

Tests unitaires

• Tester des petits bouts des programmes Avant leur intégration

• A la main ou automatique Répétabilité ? Régression ?

• Plus ou moins exhaustifs• Conditions ± réelles• Développement orienté Test (TDD)

10

Page 11: C2 - Langage C - ISIMA 1 - Deuxieme partie

Et encore ?

• Documentation Doxygen

• Analyse statique de qualité de code ? Cppcheck SonarQube Les compilateurs (clang & gcc)

11

Page 12: C2 - Langage C - ISIMA 1 - Deuxieme partie

COMPILATION SÉPARÉE& MAKEFILE

Page 13: C2 - Langage C - ISIMA 1 - Deuxieme partie

Structure d’un programme classique

• Inclusions des bibliothèques• Définition des macros et constantes• Déclaration des types personnels• Déclaration et initialisation

des variables globales si nécessaires• Définition des fonctions

Fonction main()

13

Tout ce qui est utilisé doit être déclaré sans ambiguïté.Attention aux mots réservés !

Page 14: C2 - Langage C - ISIMA 1 - Deuxieme partie

Mots réservés

14

autobreak case char continue const default do double else extern float for goto if intlongregister return short sizeof static struct switch typedefunion unsignedwhile

Page 15: C2 - Langage C - ISIMA 1 - Deuxieme partie

Définition des fonctions ?

• Principe : on ne peut utiliser que des choses connues = déclarées au préalable

• Déclarer, c’est donner un prototype ou une signature

• Déclarations anticipées (ou forward)• Définition = prototype et le corps de la fonction

15

NOM + types des paramètres + type de retour

float min(float, float);

Page 16: C2 - Langage C - ISIMA 1 - Deuxieme partie

#include <stdio.h>

int main() {

int x = 3, y = 5; printf("%d", somme(x, y)); return EXIT_SUCCESS;}

int somme(int a, int b) { return a+b;}

16

Page 17: C2 - Langage C - ISIMA 1 - Deuxieme partie

#include <stdio.h>

int somme(int a, int b) { return a+b;}

int main() {

int x = 3, y = 5; printf("%d", somme(x, y)); return EXIT_SUCCESS;}

17

Page 18: C2 - Langage C - ISIMA 1 - Deuxieme partie

#include <stdio.h>

int somme(int a, int b);

int main() { int x = 3, y = 5; printf("%d", somme(x, y)); return EXIT_SUCCESS;}

int somme(int a, int b) { return a+b;}

18

Page 19: C2 - Langage C - ISIMA 1 - Deuxieme partie

19

Mettre en œuvre la compilation séparée …

• Au départ : un gros programme Pas facile à appréhender / de se déplacer Hétérogène

• Des fonctions de stats• Des fonctions de maths

• Séparer en modules Regroupement thématique Plus facile à lire Réutilisabilité

Page 20: C2 - Langage C - ISIMA 1 - Deuxieme partie

20

GROS PROGRAMME

PROGPRINCIPAL

MODULESTATS

MODULEMATHS

Le contenu des fichiers est vu plus tard…

Page 21: C2 - Langage C - ISIMA 1 - Deuxieme partie

21

#include <stdio.h>

#define PI 3.14#define CONST_STATS 1000

int globale;

int math1(int i) { … }

int stat1(int i, float tab[]) { … math1(j)…}

int main() { stat1(math1(m), t); return 0;}

Page 22: C2 - Langage C - ISIMA 1 - Deuxieme partie

22

Les fichiers ???

• Séparation en fonction Du thème De la réutilisation possible

• Eviter les variables globales dans les modules• En C, on peut utiliser un élément à partir du

moment où il est déclaré ! Fichier de déclaration fichiers entêtes .h► Fichier d'implémentation fichiers .c►

Page 23: C2 - Langage C - ISIMA 1 - Deuxieme partie

23

/* Fichier maths.c */

#include <stdio.h>#include "maths.h"

int math1(int i) { … }

int math2(float tab[], int i) { …}

maths.cContient toutes les fonctions mathématiques

Page 24: C2 - Langage C - ISIMA 1 - Deuxieme partie

24

/* Fichier stats.c */#include <stdio.h>#include "maths.h"#include "stats.h"

int stat1(int i, float tab[]) { … math1(j)… …}

float stats2(int i, float tab[]) { …}

stats.cContient toutes les fonctions statistiques

Page 25: C2 - Langage C - ISIMA 1 - Deuxieme partie

25

/* Programme principal */

#include <stdio.h>#include "stats.h"

/* inclure maths.h est optionnel */

int globale;

void main() { … /* appel de fonctions de stats.h appel de fonction de maths.h */ …}

Programme principalPlus facile à lire car plus de code "parasite"

Page 26: C2 - Langage C - ISIMA 1 - Deuxieme partie

26

/* Fichier maths.h INCOMPLET */

#define PI 3.14

int math1(int);int math2(float[], int);

Un fichier entête…

• Déclaration des fonctions Prototype Signature

• Pas de code• Pas de nom aux variables

Page 27: C2 - Langage C - ISIMA 1 - Deuxieme partie

27

Les gardiens

• Un identifiant doit être unique

• Eviter les redéfinitions• Eviter les inclusions multiples

A inclut B qui inclut C C inclut A

PROTEGER SYSTEMATIQUEMENT UN FICHIER ENTETE

Page 28: C2 - Langage C - ISIMA 1 - Deuxieme partie

28

/* Fichier maths.h avec gardiens */

#ifndef __LOIC_MATHS_H__#define __LOIC_MATHS_H__

#define PI 3.14

int math1(int);int math2(float[], int);

#endif

Il n'est pas nécessaire de déclarer les fonctions locales au fichier maths.c, ie celles qui sont uniquement définieset appelées dans maths.c

Page 29: C2 - Langage C - ISIMA 1 - Deuxieme partie

Variable globale

• Utilisation limitée et thématique Code moins réutilisable Collision de nom

29

/* Définition dans fichier c */int globale = 0;

/* Déclaration dans fichier entête */extern int globale;

Gestion d"erreurs

Page 30: C2 - Langage C - ISIMA 1 - Deuxieme partie

30

Compilation séparée

• 3 fichiers : prog.c maths.c stats.c• Compilation des sources en .objets

• Edition des liens

gcc –c prog.cgcc -c maths.cgcc –c stats.c

gcc prog.o maths.o stats.ogcc –o prog prog.o maths.o stats.o

prog.omaths.ostats.o

-g ? -lX11 ?

Page 31: C2 - Langage C - ISIMA 1 - Deuxieme partie

31

Comment compiler ?

1. Écrire les différentes lignes de commandes correspondantes (fastidieux)

2. Ecrire un petit programme shell qui lance les différentes compilations (mieux)

3. Utiliser un programme spécial make (obligatoire)

Page 32: C2 - Langage C - ISIMA 1 - Deuxieme partie

32

Commande make

• Commande/utilitaire système• Détection "automatique" des fichiers ayant besoin

d'être recompilés• Edition des liens si nécessaire• Informations dans un fichier texte

Makefile ou makefile• Autres utilisations :

Nettoyage des fichiers temporaires (objet, …) Installation dans un répertoire particulier

Page 33: C2 - Langage C - ISIMA 1 - Deuxieme partie

33

Makefile

• Fichier texte au format très strict• Constitué de règles (commandes)

Fichiers à compiler Fichier exécutable dont il faut faire l'édition de liens Commandes nommées

• Exécuté par

$make $make règle

Page 34: C2 - Langage C - ISIMA 1 - Deuxieme partie

34

Règle

• Exécution d'une règle Cible qui n'existe pas Une dépendance est plus récente que la cible La première règle est exécutée par make Spécifique : make CIBLE (nom)

# commentaireCIBLE : DEPENDANCES <TAB> COMMANDES

Page 35: C2 - Langage C - ISIMA 1 - Deuxieme partie

35

Variable

• Définition

• Utilisation

NOM = liste de fichiers \ <TAB> suite de la liste

$(NOM)

Page 36: C2 - Langage C - ISIMA 1 - Deuxieme partie

36

Règle clean

• Nom usuel pour une règle qui efface les fichiers de travail Exécutable, fichiers objets, fichiers temporaires Pas de dépendances, règle nommée

clean :<TAB> rm –f *.o

clean :<TAB> rm $(objets)

Version bourrine Version plus propre, sécuritaire

$ make clean

Page 37: C2 - Langage C - ISIMA 1 - Deuxieme partie

Exemple de makefile

37

main.h stats.h maths.h

main.c stats.c maths.c

Page 38: C2 - Langage C - ISIMA 1 - Deuxieme partie

38

# compilateur CC = gcc # options CFLAGS = -Wall -ansi –pedantic –Wextra –g –O2 LDFLAGS = -lm# liste des fichiers objets OBJ = tp.o tp_sub1.o \ <TAB> tp_sub2.o # règle de production finale tp : tp : $(OBJ) <TAB> $(CC) $(OBJ) $(LDFLAGS) -o tp # règle de production pour chaque fichier tp_sub1.o : tp_sub1.h tp.h tp_sub1.c <TAB> $(CC) -c tp_sub1.c $(CFLAGS) tp_sub2.o : tp_sub2.h tp_sub2.c<TAB> $(CC) -c tp_sub2.c $(CFLAGS) tp.o : tp.c tp.h tp_sub1.h tp_sub2.h <TAB> $(CC) -c tp.c $(CFLAGS)

Page 39: C2 - Langage C - ISIMA 1 - Deuxieme partie

39

Et maintenant ???

• Sauf petit projet, utiliser la compilation séparée• Gain de temps à utiliser le makefile

Copie d'un Makefile qui marche Attention au format du fichier (espaces, tabulations)

• Nombreuses possibilités supplémentaires Génération automatique des dépendances

(ZZ2, option -MM) Gestion de configuration Installation d'un programme

Page 40: C2 - Langage C - ISIMA 1 - Deuxieme partie

40

.h

.c

tests

Exécutable

.h

.c

tests

.h

.c

tests

Tests encore

Exécutable

Compilation séparée & Tests unitaires

Page 41: C2 - Langage C - ISIMA 1 - Deuxieme partie

RÉVISIONS / VARIABLES

Page 42: C2 - Langage C - ISIMA 1 - Deuxieme partie

42

Masquage de variable#include <stdio.h>

int a;

void f1(double a){ printf("%f\n", a);}

int main() { a = 3; f1(2.000); printf("%d\n", a); return 1;}

Page 43: C2 - Langage C - ISIMA 1 - Deuxieme partie

43

Passage des paramètres par valeur#include <stdio.h>

void f1(int a){ a=2;}

int main() { int a = 3; f1(a); printf("%d", a); return 1;}

Page 44: C2 - Langage C - ISIMA 1 - Deuxieme partie

44

int gj = 0;int gi;

int fonction1 (int p1) { int li = 1;

gj = 4; ... }

int fonction2 (int p1) { int li = 2; int gi = 3;   ... }

Variables globales ?Variables locales ?

int main () { int li = 3; gi = 5; return 0; }

Page 45: C2 - Langage C - ISIMA 1 - Deuxieme partie

45

Variable locale

• Automatique Par défaut Mot-clé auto optionnel Créée à chaque appel de fonction Détruite à chaque fin de fonction

• Statique Initialisée au premier passage dans la fonction Détruite à la fin du programme

Page 46: C2 - Langage C - ISIMA 1 - Deuxieme partie

46

int fonction1 (int p1) { static int compteur = 0;

auto int i =1; /* auto est optionnel */ printf("%d %d", ++compteur, ++i); ...

return compteur; }

int main () { printf("%d", fonction1(0)); printf("%d", fonction1(0)); printf("%d", compteur); return 0; }

Page 47: C2 - Langage C - ISIMA 1 - Deuxieme partie

47

Autres variables

• Variables externes explicites Déclaration dans l'entête en général

• Variable de type registre Pas d'adresse mémoire Accès hyper rapide Vieille optimisation (-O2)

extern int g;

register int r;

Page 48: C2 - Langage C - ISIMA 1 - Deuxieme partie

POINTEURS

Page 49: C2 - Langage C - ISIMA 1 - Deuxieme partie

49

Problèmes rencontrés

• Tableau dynamique ?• Passage des paramètres par valeur…

Pas moyen de changer facilement la valeur d'une variable passée en paramètres

Page 50: C2 - Langage C - ISIMA 1 - Deuxieme partie

50

void echange(int a, int b) { int c;  

c = a; a = b; b = c; }

int main () { int i=1, j=2;

printf("%d %d", i, j); echange(i,j); printf("%d %d", i,j); return 0; }

Page 51: C2 - Langage C - ISIMA 1 - Deuxieme partie

51

Mémoire de l'ordinateur (1)

• Tableau à une dimension Grande dimension (256Mo -> 8Go)

• Unité de base : l'octet• Gestion plus ou moins automatique• Partage entre utilisateurs

Zones protégées• Un objet prend plus ou moins de mémoire

fonction sizeof

Page 52: C2 - Langage C - ISIMA 1 - Deuxieme partie

52

Mémoire de l'ordinateur (2)

• Que trouve-t-on en mémoire ? Code du programme Données du programme (variables)

• Rangement suivant des standards Consultation possible de la mémoire Attention au segmentation fault

• Chaque élément a une adresse

Page 53: C2 - Langage C - ISIMA 1 - Deuxieme partie

53

Mémoire de l'ordinateur (3)

a

tableau tab

i

char a;int i;char tab[12];sizeof(a)

Zone protégée :• code programme courant• zone d'un autre utilisateur• …

Adresse = indice dans le tableau

Page 54: C2 - Langage C - ISIMA 1 - Deuxieme partie

54

Pointeur ? (1)

• Variable "classique"

• Opérateur & Adresse d'un objet en mémoire (l'index …)

• Pointeur Variable contenant une adresse typé

int * p; <type> * p2;

&i et &j

int i, j;

Page 55: C2 - Langage C - ISIMA 1 - Deuxieme partie

Pointeur ? (2)

55

Ac p

4

char c = 'A';char * p = &c;

4 8

printf("%c", c);printf("%c", *p);

Variable (caractère)Adresse en mémoire

Contenu pointé

Abus de langage : le « contenu du pointeur » ne désigne pas la variable c, p ne contient que l'adresse de c. Le contenu de l’adresse pointée désigne bien c.

* : Opérateur d'indirection / opérateur de déréférencement *

Page 56: C2 - Langage C - ISIMA 1 - Deuxieme partie

56

int main(){ int a, b, *p; a = 4; p = &a;

/* %x : affichage en hexa */ printf("contenu de p %p", p); printf("adresse de a %p, &a); printf("contenu pointé %d",*p); printf("contenu %d", a);

b = *p; (*p)++; printf("valeur de a est %d", a); return 0;}

Page 57: C2 - Langage C - ISIMA 1 - Deuxieme partie

57

Affectation de pointeurs

• Types compatibles

• Valeur spéciale NULL Le pointeur ne pointe sur rien A utiliser avec précaution

int * i, *j;float * f;

i = j;i = f;

Page 58: C2 - Langage C - ISIMA 1 - Deuxieme partie

58

Rappel : changer de type

• Cast• Opérateur de transtypage• Opérateur de coercition• Transformer une valeur réelle en une valeur

entière avec perte éventuelle d'informations

int i;double d;

i = (int) d;

int * pi;void * pv;

pi = (int *) pv;

Page 59: C2 - Langage C - ISIMA 1 - Deuxieme partie

59

float *f = NULL; int *g = (int *) 0;char *c = 0;

printf("%d", *f);

/* définition, fonction du compil */#define NULL 0#define NULL (void *) 0

int i;void * v = &i;int * j = (int *) v;

Page 60: C2 - Langage C - ISIMA 1 - Deuxieme partie

60

void echangeator(int *a, int *b) { int c;  

c = *a; *a = *b; *b = c; } int main () { int i=1, j=2;

printf("%d %d", i, j); echangeator(&i,&j); printf("%d %d", i,j); return 0; }

Page 61: C2 - Langage C - ISIMA 1 - Deuxieme partie

61

Pointeurs & tableaux (1)

• Un tableau est un pointeur constant

• Adresse du premier élément du tableauchar tab[10];

char *p = &tab[0];tab ?

printf ("%x %x %x ", tab, &tab[0], p);

tab tab+2 tab +9

Page 62: C2 - Langage C - ISIMA 1 - Deuxieme partie

62

POINTEUR' = POINTEUR + DEPLACEMENT Adresse adresse

Arithmétique

• Arithmétique intelligente Typée

• Nombre limité d'opérations Affectation (=) Addition, soustraction (+, -, +=, -=) Comparaison (==, !=, <, >)

p-4 p p +5++

Page 63: C2 - Langage C - ISIMA 1 - Deuxieme partie

Arithmétique "intelligente"

63

char a[10];sizeof(char) ?sizeof(a) ?

a a+2 a +9

int b[3];

b b+1 b+2

sizeof(char)

sizeof(int)

Page 64: C2 - Langage C - ISIMA 1 - Deuxieme partie

64

Pointeurs & tableaux (2)

• Deux notations : élément i

• Elément i+1 ?

tab[i]*(tab+i)*(p+i) avec p=&tab[0]

p = &tab[i];++p;=> *p

++tab

Page 65: C2 - Langage C - ISIMA 1 - Deuxieme partie

65

Pointeurs & chaînes

• 2ème cas : pointeur + chaîne en mémoire

• string.h : Fichier d'entêtes des fonctions sur les chaînes de caractères

char s1[] = "chaine1"; char * s2 = "chaine2";

Page 66: C2 - Langage C - ISIMA 1 - Deuxieme partie

66

strlen()

Page 67: C2 - Langage C - ISIMA 1 - Deuxieme partie

67

int compter3(char * chaine) {   char * s = chaine;

while (*chaine != '\0') ++chaine;

return chaine - s; }

Page 68: C2 - Langage C - ISIMA 1 - Deuxieme partie

68

strcpy()

Page 69: C2 - Langage C - ISIMA 1 - Deuxieme partie

69

Page 70: C2 - Langage C - ISIMA 1 - Deuxieme partie

Mémoire "typée"

70

sizeof(char)

sizeof(int)sizeof(long int)

sizeof(float)sizeof(double)

sizeof(int *)sizeof(double *)sizeof(void *)

Page 71: C2 - Langage C - ISIMA 1 - Deuxieme partie

71

Allocation dynamique de mémoire ?

• Allouer de la mémoire = réserver une zone mémoire contiguë Pas toujours possible

• Dynamique : en cours d'exécution de programme (et non au moment de la compilation)

Page 72: C2 - Langage C - ISIMA 1 - Deuxieme partie

72

malloc()

• Allocation d'un bloc contigu de mémoire Erreur, si le bloc est trop grand

• Demande d'un nombre d'octets à calculerNombre d'éléments x Taille d'un élément

• Retour : pointeur sur le début du tableau NULL si l'allocation est impossible

void * malloc (size_t taille);

Page 73: C2 - Langage C - ISIMA 1 - Deuxieme partie

73

Libérer la mémoire (1)

• Obligatoire de rendre la mémoire demandée au système

• Ce n'est PAS AUTOMATIQUE• Paramètre : un pointeur VALIDE

Donner la taille d'allocation n'est pas utile Tester que le pointeur est non NULL même si …

void free(void * pointeur);

Page 74: C2 - Langage C - ISIMA 1 - Deuxieme partie

74

Libérer la mémoire (2)

• Oublier de rendre la mémoire = Fuite mémoire Vers un redémarrage de la machine

• Conseil : mettre le pointeur à NULLsi la libération n'est pas faite à la fin du programme

• Outils de détection : débugger, valgrind …

if (p) free(p);p = 0;

Page 75: C2 - Langage C - ISIMA 1 - Deuxieme partie

75

int taille; int * tableau;

printf("Taille du tableau ? "); scanf("%d", &taille);

tableau = (int *) malloc (taille*sizeof(int));

if (tableau == NULL) { printf("allocation mémoire impossible"); } else { /* l'allocation mémoire a eu lieu */ /* … */

  free(tableau);}

Page 76: C2 - Langage C - ISIMA 1 - Deuxieme partie

76

calloc()• Comportement identique à malloc()• Initialisation des éléments du tableau à 0

Connaître la taille d'un élément pour le mettre à 0 calloc() prend plus de temps que malloc()

• Paramètres différents de malloc() Nombre d'éléments Taille d'un élément

• Retour : pointeur sur le début du tableau NULL si l'allocation est impossible

void * calloc (size_t nb_elem, size_t taille);

Page 77: C2 - Langage C - ISIMA 1 - Deuxieme partie

77

realloc()

• Redimensionner la taille d'un tableau en mémoire

• Problème : demander plus de mémoire1. Ajout au bloc précédent2. Allocation d'un nouveau bloc

et déplacement du bloc initial3. Plus assez de mémoire disponible

• Fragmentation de la mémoire

Page 78: C2 - Langage C - ISIMA 1 - Deuxieme partie

78

Cas 1

Blocs déjà alloués (protégés)Blocs déjà alloués (à nous)Blocs supplémentaires

Nombre de blocs supplémentaires demandé raisonnable = allocation contiguë possible

Page 79: C2 - Langage C - ISIMA 1 - Deuxieme partie

79

Cas 2

Blocs déjà alloués (protégés)Blocs déjà alloués (à nous)Blocs supplémentaires

Nombre de blocs supplémentaires demandé trop grand = allocation contigüe impossible

COPIE

Page 80: C2 - Langage C - ISIMA 1 - Deuxieme partie

80

Cas 3

Blocs déjà alloués (protégés)Blocs déjà alloués (à nous)Blocs supplémentaires

Nombre de blocs supplémentaires demandé trop grand = déplacement impossible

Page 81: C2 - Langage C - ISIMA 1 - Deuxieme partie

81

Allocation dynamique / Résumé

void * malloc (size_t taille);void * calloc (size_t nb_elem, size_t taille);void * realloc(void * pointeur, size_t nouvelle_taille);

void * /* type pointeur universel */ /* transtypage(cast) obligatoire */

size_t /* type entier positif */

void free(void * pointeur);

NULL

Page 82: C2 - Langage C - ISIMA 1 - Deuxieme partie

82

Tableau de pointeurs

• Pointeur = un type de variable• Possibilité d'en faire des tableaux

int * tableau [80];int i = 10;

tableau[0] = &i;printf("%d", (*tableau[0]));

Page 83: C2 - Langage C - ISIMA 1 - Deuxieme partie

83

Erreurs typiques char * s; s = "chaine2";

char * s; scanf("%s",s);

char s1[10] = "chaine1"; char s2[10]; s2 = s1;

Page 84: C2 - Langage C - ISIMA 1 - Deuxieme partie

STRUCTURE

Page 85: C2 - Langage C - ISIMA 1 - Deuxieme partie

85

Problème …

• On ne peut retourner qu'un seul élément par fonction

• En algorithmique

return variable;

retourne (élement1, élément2);

Page 86: C2 - Langage C - ISIMA 1 - Deuxieme partie

86

Exemple hypothétique

• Gérer un concours de poker au BDE surnom : 80 caractères score (unité : EuroZZ) : entier

Jouer en ligne est dangereux pour la santé … et le porte monnaie

Page 87: C2 - Langage C - ISIMA 1 - Deuxieme partie

87

Réalisation

• Solution à deux balles : 2 tableaux

• Nom• Score

• Solution propre Un tableau d'un type complexe

#define TAILLE 30int score [TAILLE];char surnoms [TAILLE][80];

Page 88: C2 - Langage C - ISIMA 1 - Deuxieme partie

88

Type complexe ?

• Réunir des informations dans un tout Créer un nouveau type de données Personnalisé

2 champs : nom et score

struct joueur { char nom[80]; int score;};

Page 89: C2 - Langage C - ISIMA 1 - Deuxieme partie

• Déclaration de variable

• Accéder à un champ d'une variable

• Taille en mémoire du type complexe

89

struct joueur zz;

sizeof(struct joueur);

Manipulations de base

zz.score = 0;scanf("%s", zz.nom);

Page 90: C2 - Langage C - ISIMA 1 - Deuxieme partie

90

Tableau de structures

struct joueur joueurs[50];int i;

for(i = 0; i < 50; ++i) { joueurs[i].score = 0; strcpy(joueurs[i].nom, "");}

Page 91: C2 - Langage C - ISIMA 1 - Deuxieme partie

91

Pointeur de structure

• Déclaration d'un pointeur

• Accéder à un champ (pointeur non NULL)

• Allocation dynamique

struct joueur * psj = &zz;

psj = (struct joueur *) malloc(50*sizeof(struct joueur));

(*psj).score psj->score

Page 92: C2 - Langage C - ISIMA 1 - Deuxieme partie

92

typedef

• Renommer un type existant L'ancien nom est toujours disponible

1. Simplifier le nom des structures2. Eviter les erreurs avec les pointeurs

typedef ancien_nom nouveau_nom;

Page 93: C2 - Langage C - ISIMA 1 - Deuxieme partie

93

typedef & structures (1)

struct joueur{ char nom[80]; int score;};typedef struct joueur joueur_t;

struct joueur zz1;joueur_t zz2;

struct joueur * pzz1;joueur_t * pzz2;

Page 94: C2 - Langage C - ISIMA 1 - Deuxieme partie

94

typedef & structures (2)

• Condenser les deux écritures…

typedef struct joueur { char nom[80]; int score;} joueur_t;

struct joueur zz1;joueur_t zz2;

Page 95: C2 - Langage C - ISIMA 1 - Deuxieme partie

95

typedef & structures (3)

• Simplifier ?

• Structure "anonyme"

typedef struct { char nom[80]; int score;} joueur_t;

struct joueur zz1;

joueur_t zz2;

Page 96: C2 - Langage C - ISIMA 1 - Deuxieme partie

96

Structure autoréférentielle (1)

• Structure qui contient un pointeur sur un élément de même type

typedef struct joueur { char nom[80]; int score; struct joueur * suivant;} joueur_t;

Page 97: C2 - Langage C - ISIMA 1 - Deuxieme partie

97

Structure autoréférentielle (2)

• Erreurs classiques : Pas de structure anonyme Pas possible d'utiliser le nom raccourci avec typedef

• Obligatoire pour représenter Bon nombre de structures de données Liste chaînée, arbre, …

Page 98: C2 - Langage C - ISIMA 1 - Deuxieme partie

98

Liste chaînée

nom score suivant

nom score suivant

nom score suivant

NULL

Tête de la liste chaînée ?

Cellules allouées dynamiquement

Page 99: C2 - Langage C - ISIMA 1 - Deuxieme partie

99

Tête de la liste chaînée

1. Un pointeur simple NULL liste vide Non NULL pointe sur le premier élément

2. Une tête fictive Une structure dont on ne se sert pas du contenu Seul le champ SUIVANT est utile

joueur_t * ptete;

joueur_t tetefictive;

Page 100: C2 - Langage C - ISIMA 1 - Deuxieme partie

TD : liste chaînée

• Liste vide ?• Liste à un élément ?• Liste quelconque ?

• Insertion d'un élément en tête• Insertion d'un élément en fin

Pointeur de fin• Insertion / Suppression quelconque• Opération hors fonction ou appel de fonction

100

Page 101: C2 - Langage C - ISIMA 1 - Deuxieme partie

101

Liste vide

Liste à 1 élément

Liste à 2 éléments

suivant NULL

suivant suivant NULL

suivant suivant suivant NULL

Page 102: C2 - Langage C - ISIMA 1 - Deuxieme partie

Affichage de la liste

102

suivant suivant suivant NULL

courant NULL

Page 103: C2 - Langage C - ISIMA 1 - Deuxieme partie

103

TD : suppression de la liste (avec tête fictive)

Page 104: C2 - Langage C - ISIMA 1 - Deuxieme partie

Saisie d’une chaine

104

fgets(chaine, 50, stdin);

scanf("%s", chaine);

loic⏎

loic yon⏎

tropgrand⏎ char chaine[5];

char chaine[50];

char chaine[50];

scanf

scanf

scanf

fgets

fgets

fgets

Page 105: C2 - Langage C - ISIMA 1 - Deuxieme partie

QUELQUES PRÉCISIONS SUR LES POINTEURS

1. Tableau multidimensionnel2. typedef & pointeurs3. Pointeur constant

Page 106: C2 - Langage C - ISIMA 1 - Deuxieme partie

106

Tableau multidimensionnel (1)

• Tableau de 4 lignes et 3 colonnes

• Stockage contigu, ligne par ligneint tableau [4][3];

Début du tableau en mémoire

Ligne 1 Ligne 2 Ligne 3 Ligne 4

Page 107: C2 - Langage C - ISIMA 1 - Deuxieme partie

107

Tableau multidimensionnel (2)

• Prototype La taille de la ligne (nb de colonnes) est

nécessaire Pas le nombre de lignes

int tableau [][3];

Page 108: C2 - Langage C - ISIMA 1 - Deuxieme partie

108

Accéder à un élément

• Tableau à une dimension

• Tableau multidimensionnel

ligne[i]*(ligne +i)

tableau[1][2]*(tableau[1]+2)*(*(tableau+1)+2)

Attention à la lisibilité !!!

Page 109: C2 - Langage C - ISIMA 1 - Deuxieme partie

109

Tableau à 2 dimensions dynamique ?

1. Implémentation avec un tableau à une dimension

Taille de la ligne : n Trouver l'élément de la ligne i et colonne j :

2. Implémentation avec une dimension maximale et une dimension libre

i*n+j

int * tab1;

int * tab2[MAX];

Page 110: C2 - Langage C - ISIMA 1 - Deuxieme partie

110

Tableau à 2 dimensions dynamique• Choisir la représentation par lignes ou par

colonnes

• Allouer un premier tableau de pointeurs Un élément pointe vers une ligne ou une colonne

• Allouer chaque ligne/colonne

int ** tab3;

tab3

Page 111: C2 - Langage C - ISIMA 1 - Deuxieme partie

111

Tableau dynamique / synthèse

int * tab1;

int * tab2[MAX];

dynamique calcul

moins de pointeurs pas complètement dynamique

int ** tab3; dynamique vrai tableau complexe

Page 112: C2 - Langage C - ISIMA 1 - Deuxieme partie

112

typedef

• Utiliser typedef pour éviter un maximum d'erreurs avec les pointeurs

• "Créer" un type pointeur Manipuler un pointeur comme une variable

pour oublier les pointeurs de pointeurs

• Exemple : échanger deux variables pointeurs

Page 113: C2 - Langage C - ISIMA 1 - Deuxieme partie

void echange2pointeurs (int **a, int **b) { int * c;  

c = *a; *a = *b; *b = c; }

113

Echanger deux pointeurs

typedef int * pint;

void echange2pointeurs(pint* a, pint *b) { pint c;  

c = *a; *a = *b; *b = c; }

Page 114: C2 - Langage C - ISIMA 1 - Deuxieme partie

114

Modifier un pointeur ? (1)void liberer(joueur_t * tete) { /* … */ if (tete) free(tete); tete = 0;}

int main() { joueur_t * tete = NULL; ajouter_element(&tete, element); /* utiliser tete */ liberer(tete); ajouter_element(&tete, element); /* utiliser tete */ liberer(tete); }

Liste chaînée avec vrai pointeur en têteRéutiliser le pointeur

Page 115: C2 - Langage C - ISIMA 1 - Deuxieme partie

115

Modifier un pointeur ? (2)void liberer(joueur_t ** tete) { /* … */ if (*tete) free(*tete); *tete = 0;}

int main() { joueur_t * tete = NULL; ajouter_element(&tete, element); /* utiliser tete */ liberer(&tete); ajouter_element(&tete, element); /* utiliser tete */ liberer(&tete); }

Liste chaînée avec vrai pointeur en têteRéutiliser le pointeur

Page 116: C2 - Langage C - ISIMA 1 - Deuxieme partie

116

typedef joueur_t * pjoueur_t;

void liberer(pjoueur_t * tete) { /* … */ if (*tete) free(*tete); *tete = 0;}

int main() { pjoueur_t tete = NULL; ajouter_element(&tete, element); /* utiliser tete */ liberer(&tete); ajouter_element(&tete, element); /* utiliser tete */ liberer(&tete); }

Cacher le double pointeur ..

Page 117: C2 - Langage C - ISIMA 1 - Deuxieme partie

117

const (1)

• S’engager à ne pas modifier une variable Valeur fixée à l'initialisation

• Ne peut pas servir pour initialiser un tableau

(sauf depuis la norme C99)

/* notations équivalentes */const float pi = 3.14;float const pi = 3.14;

const int I = 100; float tab[I];

Page 118: C2 - Langage C - ISIMA 1 - Deuxieme partie

118

const (2)

• Pointeur

• Pointeur

• Pointeur

const char * sz1;char const * sz2;

char * const sz3 = …;

char const * const sz4 = …;

Page 119: C2 - Langage C - ISIMA 1 - Deuxieme partie

MACROS

1. Type constant2. Type fonction

Page 120: C2 - Langage C - ISIMA 1 - Deuxieme partie

120

Rappels : constante

• Mot-clé #define• Fausse constante

Remplacée par le préprocesseur• Pas de point-virgule• Convention de nommage : en majuscules

#define N 100

Page 121: C2 - Langage C - ISIMA 1 - Deuxieme partie

121

fichier.c

préprocesseur

compilation

édition des liens

exécutable

erreurs

Rappel :La "Compilation"

erreursld

Page 122: C2 - Langage C - ISIMA 1 - Deuxieme partie

122

Macros

• Synonymes Macro-définition Macro-commande Macro-instruction

• 2 types de macros Type constant Type fonction

Page 123: C2 - Langage C - ISIMA 1 - Deuxieme partie

123

Macro de type constant (1)

• Synonymes Macro définition Constante symbolique

#define N 100#define PI 3.14#define EPSILON 1E-6#define NOM "loic"

#define nom texte_remplacement

PAS DE NOTION DE TYPE

Page 124: C2 - Langage C - ISIMA 1 - Deuxieme partie

float tab1[N];

#define N 100

float tab1[N];

#define N 200

float tab1[N];

#undef N

float tab1[N];

124

• Validité De la déclaration

à la fin du fichier Sauf #define Sauf #undef

• Evaluation par le préprocesseur Inconnu du compilateur

Page 125: C2 - Langage C - ISIMA 1 - Deuxieme partie

125

Macro de type constant (3)

• Constante sans valeur• Utile pour la compilation conditionnelle

#ifdef, #ifndef, #endif, #else, #elif

Gardiens

#define VARIABLE PAS DE VALEUR

Page 126: C2 - Langage C - ISIMA 1 - Deuxieme partie

126

Macro de type fonction (1)

• Macros avec paramètre[s]

• Syntaxe Pas de point-virgule (sauf…) Pas d'espace entre le nom et la parenthèse Nom en majuscules

#define nom(paramètres) texte

Page 127: C2 - Langage C - ISIMA 1 - Deuxieme partie

127

Exemple 1a

#define CARRE1(A) A*A

int i = 2;printf("%d", CARRE1(i));

Page 128: C2 - Langage C - ISIMA 1 - Deuxieme partie

128

Exemple 1b

#define CARRE1(A) A*A

int i=2;printf("%d", CARRE1(i+1));/* résultat ? */

Page 129: C2 - Langage C - ISIMA 1 - Deuxieme partie

129

Macro de type fonction (2)

• Substitution de texte• Ce ne sont PAS des fonctions !

Pas d'appel de fonction => plus rapide• Attention

Aux messages d'erreur du compilateur Aux effets de bord Parenthèsage systématique

Page 130: C2 - Langage C - ISIMA 1 - Deuxieme partie

130

Exemple 1c

#define CARRE2(A) (A*A)

#define CARRE3(A) ((A)*(A))

Page 131: C2 - Langage C - ISIMA 1 - Deuxieme partie

131

Exemple 2a

#define MAX1(A,B) A>B?A:B

int i = 2;int j = 3;printf("%d", MAX1(i,j));

Page 132: C2 - Langage C - ISIMA 1 - Deuxieme partie

132

Exemple 2b

#define MAX1(A,B) A>B?A:B

int i = 2;int j = 3;printf("%d", 6+MAX1(i,j));

Page 133: C2 - Langage C - ISIMA 1 - Deuxieme partie

133

Exemple 2c

#define MAX2(A,B) (((A)>(B))?(A):(B))

int i = 2;int j = 3;printf("%d\t", 6 + MAX2(i,j));printf("%d\n", MAX2(i++, j++));printf("i = %d j = %d\n", i, j);

Page 134: C2 - Langage C - ISIMA 1 - Deuxieme partie

134

Avec une fonction ?

• Si l'on veut calculer le maximum avec une fonction, il faut autant de fonctions qu'il y a de type

• Identification de paramètres Paramètres évalués une fois

int max(int a, int b){ return a > b ? a : b;}max(i++, j++) renvoie le bon résultat

Page 135: C2 - Langage C - ISIMA 1 - Deuxieme partie

135

Exemple 3#define MALLOC(TYPE,NOMBRE) \ ((TYPE *)malloc(sizeof(TYPE)*NOMBRE))

int   * pi, * pj;float * pf;

pi = MALLOC(int, 10);

pf = MALLOC(float, 100);

pj = MALLOC(float, 100);

Page 136: C2 - Langage C - ISIMA 1 - Deuxieme partie

136

Ecrire une "fonction" d'allocation

void allouer(void ** pointeur, int nb, int taille) { if ((*pointeur = malloc(nb*taille)) == NULL) erreur(); }

int *pi;

allouer(&pi, 10, sizeof(int));

Page 137: C2 - Langage C - ISIMA 1 - Deuxieme partie

137

Ecrire une macro d'allocation

#define ALLOUER(PTR,NB,TYPE) \ if ((PTR = (TYPE *)malloc(NB*sizeof(TYPE))) \ == NULL) erreur()

pas de pointeur de pointeur attention aux messages du compilo

int *pi;ALLOUER(pi, 10, int);

Page 138: C2 - Langage C - ISIMA 1 - Deuxieme partie

138

Ecrire une macro complexe

#define MACRO(ARG1, ARG2) { \ fonction(ARG1); \ fonction(ARG2); \}

#define MACRO(ARG1, ARG2) do { \ fonction(ARG1); \ fonction(ARG2); \} while (0)

if (a!=b) MACRO(a, b) ; else fonction(a);

if (a!=b) fonction(b) ; else fonction(a);

Page 139: C2 - Langage C - ISIMA 1 - Deuxieme partie

139

Aller plus loin… opérateur #

• Entoure l'élément de guillemets• Note :

#define DUMP1(X) printf("%s == %d", #X, X)

"A" "B""AB"

#define DUMP2(X) printf(#X " == %d", X)

int a = 1;DUMP1(a); /* affiche a==1 */DUMP2(a); /* affiche a==1 */

Page 140: C2 - Langage C - ISIMA 1 - Deuxieme partie

140

Aller plus loin… opérateur ## (1)

• Concatène deux éléments

#define COLLER(A,B) A##B

COLLER(COLLER(A,1),2) donne COLLER(A,1)2 et non pas A12

COLLER(A, 1) A1

## empêche un développement supplémentaire

Page 141: C2 - Langage C - ISIMA 1 - Deuxieme partie

141

Aller plus loin… opérateur ## (2)

• Concatène deux éléments

#define COLLER(A,B) A##B#define XCOLLER(A,B) COLLER(A,B)

XCOLLER(XCOLLER(A,1),2) A12

Page 142: C2 - Langage C - ISIMA 1 - Deuxieme partie

142

Synthèse• Avantages

Simplification d'écriture de code Rapidité par rapport aux fonctions

• Désavantages Augmente la taille du code Effets de bords Lenteur à cause de l'évaluation systématique

• Guide de style Nom en MAJUSCULES

Page 143: C2 - Langage C - ISIMA 1 - Deuxieme partie

143

Note sur la vitesse d'exécution

• Appel de macro Pas d'appel de fonction Pas de saut mémoire Pas de paramètres empilés

• Évaluation systématique des arguments Dans MAX, un des arguments est évalué deux

fois

Perte de temps ???

MAX(f(x), g(x))

Gain de temps

Page 144: C2 - Langage C - ISIMA 1 - Deuxieme partie

LIGNE DE COMMANDE

Page 145: C2 - Langage C - ISIMA 1 - Deuxieme partie

145

Ligne de commande ?

• Fournir des informations au programme qui s'exécute à partir du système

• Solution : le point d'entrée du programme La fonction main() Normes ANSI et ISO

$programme param1 –l –r $programme "une chaine avec espaces"

Page 146: C2 - Langage C - ISIMA 1 - Deuxieme partie

146

Jusqu'à maintenant…

void main();

void main(void);

int main();

Pas d'autres types de retour possibles

Page 147: C2 - Langage C - ISIMA 1 - Deuxieme partie

147

Fonction "main"int main(int argc, char ** argv);

int main(int argc, char * argv[]);

• Seuls prototypes minimaux reconnus par les normes ANSI et ISO

• Tout programme renvoie un état• Paramètres séparés par au moins un espace

Page 148: C2 - Langage C - ISIMA 1 - Deuxieme partie

148

argc / argv

• arg count Nombre d'éléments de la ligne de commande

• arg vector Liste des arguments (chaînes de caractères) Au moins un argument, le nom du programme

• Norme

argv[0] -> nom du programmeargv[argc-1] -> dernier paramètreargv[argc] -> NULL

Page 149: C2 - Langage C - ISIMA 1 - Deuxieme partie

149

Transformer les arguments

• Tous les paramètres sont des chaînes de caractères…

• Conversion éventuelle dans un type différent

• Exemple : transformer en entier

int atoi(char *);sscanf(chaine, format, variables);

Page 150: C2 - Langage C - ISIMA 1 - Deuxieme partie

FICHIERS (BINAIRES)

1. Compléments sur les fichiers2. Fichiers binaires

Page 151: C2 - Langage C - ISIMA 1 - Deuxieme partie

151

Fichiers• Texte

Compréhensible par l'humain Editeur de texte Par défaut

• Binaire Informations codées (illisibles) Périphériques UNIX Préciser le mode b

• Traitement similaire• Flot / Flux

Page 152: C2 - Langage C - ISIMA 1 - Deuxieme partie

152

Un fichier…• Informations suivantes

Nom et type du fichier Mode d'ouverture (Lecture/Ecriture) Emplacement sur le disque Emplacement de la mémoire tampon en RAM

• Fichiers standards prédéfinis stdin stdout stderr

Page 153: C2 - Langage C - ISIMA 1 - Deuxieme partie

153

Structure FILE

• Bibliothèque stdio.h Stocker des informations sur le fichier à

manipuler• Mémoire-tampon

De taille BUFSIZ (pas de E) Machine asynchrone

Page 154: C2 - Langage C - ISIMA 1 - Deuxieme partie

154

Structure FILE

typedef struct _iobuf { char* _ptr; int _cnt; char* _base; int _flag; int _file; int _charbuf; int _bufsiz; char* _tmpfname;} FILE;

Issu du stdio.h de MinGW

Page 155: C2 - Langage C - ISIMA 1 - Deuxieme partie

155

FOPEN_MAX

• Nombre limité de fichiers ouverts (ressources systèmes)

• Au moins 8• Fichiers déjà ouverts

stdin stdout stderr

Page 156: C2 - Langage C - ISIMA 1 - Deuxieme partie

156

Modes d'utilisation

• LECTURE (r) read

• ECRITURE (w) write

• AJOUT (a) append

• Panachage : r+, w+, a+

Page 157: C2 - Langage C - ISIMA 1 - Deuxieme partie

157

Utilisation des fichiers binaires

• Ouverture/création/fermeture fopen / fclose

• Lecture / Ecriture Séquentielle fread / fwrite Aléatoire fseek / ftell

• Gestion des fichiers feof / ferror / fflush

Page 158: C2 - Langage C - ISIMA 1 - Deuxieme partie

158

fopen / fclose

• "Ouvrir" un fichier dont le nom est donné Chemin valide Mode "rb", par exemple

• "Fermer" le fichier Nécessaire Force l'écriture des données non encore écrites Vide les mémoires tampons

FILE * fopen(const char * nom, char * mode);

int fclose(FILE * fic);

Page 159: C2 - Langage C - ISIMA 1 - Deuxieme partie

159

fread

1. Lire des objets d'un flux donné2. Les placer en mémoire

Quoi : lire nbobj objets de taille taille De : fic Où : zone mémoire, tableau ptr Retourne le nombre d'éléments effectivement lus EOF en cas d'erreur

size_t fread(void *ptr, size_t taille, size_t nbobj, FILE * fic);

Page 160: C2 - Langage C - ISIMA 1 - Deuxieme partie

160

fwrite

1. Lire les données en mémoire2. Ecrire des objets dans un flux donné

Quoi : écrire nbobj objets de taille taille De : zone mémoire ptr Où : fichier fic Retourne le nombre d'éléments effectivement écrits EOF en cas d'erreur

size_t fwrite(const void *ptr, size_t taille, size_t nbobj, FILE * fic);

Page 161: C2 - Langage C - ISIMA 1 - Deuxieme partie

161

Gestion des flux (1)

• Retourne une valeur non nulle si l'indicateur de fin de fichier est positionné

• Retourne une valeur non nulle si l'indicateur d'erreur de fichier est positionné

int feof(FILE * fic);

int ferror(FILE * fic);

#define EOF (-1)

Page 162: C2 - Langage C - ISIMA 1 - Deuxieme partie

162

Gestion des flux (2)

• Vide la mémoire tampon associée à fic• Force l'écriture/lecture• Vide tous les tampons si fic est nul• NON défini pour les flux d'entrée

int fflush(FILE * fic);

Page 163: C2 - Langage C - ISIMA 1 - Deuxieme partie

163

Accès aléatoire (1)

• Accès au fichier à un endroit particulier Gestion d'un curseur

• Retourne la position du curseur fichier

long ftell(FILE * fic);

Page 164: C2 - Langage C - ISIMA 1 - Deuxieme partie

164

Accès aléatoire (2)

• Déplacer le pointeur/curseur fichier dep :déplacement (+ ou-) o : origine dans les valeurs suivantes

• Retourne 0 si le déplacement est effectué

int fseek(FILE * fic, long dep, int o);

SEEK_SET : du début du fichier (dep>0)SEEK_END : de la fin de fichier (dep<0)SEEK_CUR : de la position courante

Page 165: C2 - Langage C - ISIMA 1 - Deuxieme partie

165

Exemple

• Gestion d'un répertoire personnel Nom du contact Numéro de téléphone

• Tableau en mémoire À écrire/lire sur le disque

typedef struct { char nom[30]; char num[10]; } entree_t;

Page 166: C2 - Langage C - ISIMA 1 - Deuxieme partie

166

void enregistrer(entree_t repertoire[], int taille){ FILE * fichier = fopen("sauvegarde", "wb"); int res = 0; if (fichier) { res = fwrite(repertoire, sizeof(entree_t), taille, fichier); if (res != taille) fprintf(stderr, "probleme\n"); fclose(fichier); }}

Page 167: C2 - Langage C - ISIMA 1 - Deuxieme partie

167

int lire(entree_t repertoire[]){ FILE * fichier = fopen("sauvegarde", "rb"); int taille = 0; if (fichier) { while(!feof(fichier)) fread(&repertoire[taille++], sizeof(entree_t), 1, fichier); fclose(fichier); } return taille; }

Page 168: C2 - Langage C - ISIMA 1 - Deuxieme partie

STRUCTURES PARTICULIÈRES

1. enum2. union3. champs de bits

Page 169: C2 - Langage C - ISIMA 1 - Deuxieme partie

169

Enumération (1)

printf("On est %d", mardi);

#define LUNDI 0#define MARDI 1#define MERCREDI 2#define JEUDI 3#define VENDREDI 4#define SAMEDI 5#define DIMANCHE 6

printf("On est encore %d", MARDI);

const int lundi = 0;const int mardi = 1;const int mercredi = 2;const int jeudi = 3const int vendredi = 4;const int samedi = 5;const int dimanche = 6;

Page 170: C2 - Langage C - ISIMA 1 - Deuxieme partie

170

Enumération (2)

enum SEMAINE { lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche};

enum SEMAINE jour;for (jour = lundi; jour <= vendredi; ++jour) printf("On travaille…");

Page 171: C2 - Langage C - ISIMA 1 - Deuxieme partie

171

Point de vue du compilateur

enum SEMAINE { lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche};

0

6

• Affecte une valeur entière à chaque élément

• Sans précision Commence à zéro Incrémente la valeur

pour chaque nouvel élément

Page 172: C2 - Langage C - ISIMA 1 - Deuxieme partie

172

"Perturber" le compilo

enum SEMAINE { lundi = 1, mardi, mercredi, jeudi, vendredi, samedi, dimanche};

1

7enum PAYS { belgique = 32, france, angleterre = 44, etats_unis = 1, allemagne = 49, royaume_uni = 44};

Page 173: C2 - Langage C - ISIMA 1 - Deuxieme partie

173

Compatibilité ?

enum PAYS pays;

pays = france;

pays = mercredi;

Page 174: C2 - Langage C - ISIMA 1 - Deuxieme partie

174

enum vs macros

• Constante symbolique Substituée par le préprocesseur N'existe pas pour le compilateur

• enum Traduction en "entiers" Vérification de type Vraies constantes

Page 175: C2 - Langage C - ISIMA 1 - Deuxieme partie

175

Union (1)

• Ranger des variables différentes dans le même espace mémoire

• Stockage d’un champ à la fois

union u{ int i; double d;} u1;

struct s{ int i; double d;} s1;

sizeof ?

Page 176: C2 - Langage C - ISIMA 1 - Deuxieme partie

176

Union (2)

typedef struct { double rho; double theta;} polaire_t;

typedef struct { double reel; double imag;} cartesien_t;

typedef union { cartesien_t car; polaire_t pol;} complexe_u;

typedef struct { complexe_u val; enum FORMES forme;} complexe_t;

enum FORMES { CAR, POL};

Page 177: C2 - Langage C - ISIMA 1 - Deuxieme partie

177

Union (3)double modulo_compl( complexe_t a){ double res;

switch (a.forme) {case CAR :

res = sqrt(a.val.car.reel*a.val.car.reel+ a.val.car.imag*a.val.car.imag);

break;case POL :

res = a.val.pol.rho;break;

default : fprintf(stderr, "Erreur\n"); }; return res;}

Page 178: C2 - Langage C - ISIMA 1 - Deuxieme partie

178

Champs de bitstypedef struct couleur1{ unsigned int R; unsigned int G; unsigned int B; unsigned int A;} couleur1_t; typedef struct couleur2

{ unsigned int R:8; unsigned int G:8; unsigned int B:8; unsigned int A:8;} couleur2_t;

• types obligatoires : int, unsigned int

Page 179: C2 - Langage C - ISIMA 1 - Deuxieme partie

FONCTION À NOMBRE D'ARGUMENTS VARIABLE

Page 180: C2 - Langage C - ISIMA 1 - Deuxieme partie

180

Etat des lieux

• Prototype de fonctions à nombre d'arguments fixe Liste des types

• Fonctions qui ne respectent pas ce schéma ! printf scanf Essayer de définir des fonctions avec le même

nom mais avec une liste d'arguments différents ►IMPOSSIBLE

Page 181: C2 - Langage C - ISIMA 1 - Deuxieme partie

181

Prototype

• Liste NON VIDE de paramètres fixes

• Prototype de fscanf ?

<type_retour> nom(liste_fixe, ... );

int fscanf(FILE *,char *, ...);

fscanf(fichier, "%d %d", &nb1, &nb2);

Page 182: C2 - Langage C - ISIMA 1 - Deuxieme partie

182

Utilisation (1)#include<stdarg.h>

va_start(liste, nom)

va_end(liste)

va_list

Macros dans fichier include

Type liste de paramètre

Initialiser la liste de paramètres

nom est le nom du dernier paramètre fixe de la fonction

Libération du pointeur de liste

Seulement conseillé par la norme donc … OBLIGATOIRE

Page 183: C2 - Langage C - ISIMA 1 - Deuxieme partie

183

Utilisation (2)

• Récupération paramètre par paramètre Un à chaque appel

• Types possibles int, double, pointeurs comme char *

• Types convertis char, float

va_arg(liste, type)

Page 184: C2 - Langage C - ISIMA 1 - Deuxieme partie

184

int ouvrable(char * mode, int nombre, ...) { int result = 1; char * fileName; va_list liste;

va_start(liste, nombre); while (nombre--) { fileName = va_arg(liste, char *); if (!fopen(fileName, mode)) { result = 0; break; } } va_end(liste); return result;} /* exemple d'appel */ouvrable("r", 2, "pg1.c", "pg2.c")

Page 185: C2 - Langage C - ISIMA 1 - Deuxieme partie

POINTEURS DE FONCTION

Page 186: C2 - Langage C - ISIMA 1 - Deuxieme partie

186

Une fonction ?

• Nom + type de retour + liste de paramètres

• Ce n'est pas une variable !• Nom adresse en mémoire►

• Pointeurs de fonction

Page 187: C2 - Langage C - ISIMA 1 - Deuxieme partie

187

Exemples

int (*pf1)(void);

double (*pf2)(double, double);

void (*pf3)();

On ne connaît pas les paramètres de pf3.(ancienne formulation du C)

void f3(nom1, nom2)int nom1;double nom2;{ … }

Parenthèses obligatoirespour (*nom)

Page 188: C2 - Langage C - ISIMA 1 - Deuxieme partie

188

double (*pf2)(double, double);

double max(double a, double b) { return (a > b)? a : b;}

pf2 = &max;

pf2 = max;

max(2.0, 5.0);

pf2(2.0, 5.0);

(*pf2)(2.0,5.0);

Privilégier la compréhension

Privilégier la portabilité

Page 189: C2 - Langage C - ISIMA 1 - Deuxieme partie

189

Tableau de pointeurs (1)int f1();int f2();int f3();int f4();

switch(choix) { case 0 : f1(); break; case 1 : f2(); break; case 2 : f3(); break; case 3 : f4(); break;}

Page 190: C2 - Langage C - ISIMA 1 - Deuxieme partie

190

Analogie

int choix, val;int a,b,c,d;

switch(choix) { case 0 : a = val; break; case 1 : b = val; break; case 2 : c = val; break; case 3 : d = val; break;}/* ou if … else if else … */

int t[4];

t[choix] = val;

Page 191: C2 - Langage C - ISIMA 1 - Deuxieme partie

191

Tableau de pointeurs (2)int (*tabptrfn[4]) ();

tabptrfn[0] = f1;tabptrfn[1] = f2;tabptrfn[2] = f3;tabptrfn[3] = f4;

int (*tabptrfn[]) () = { f1, f2, f3, f4 };

tabptrfn[choix] ();

OU

"SWITCH"

(*tabptrfn[choix])();(**(tabptrfn+choix))();

Page 192: C2 - Langage C - ISIMA 1 - Deuxieme partie

192

Pointeur de fonction en paramètre

double appliquer(double, double, double (*) (double, double) );

double appliquer(double a, double b, double (*pf) (double, double) ){ pf(a,b);}

appliquer(10.0, 2.0, max );

Prototype = pas de nom pour les paramètres

Page 193: C2 - Langage C - ISIMA 1 - Deuxieme partie

193

typedef

typedef ancien_nom nouveau_nom;

typedef double (*NOM) (double, double);

• Forme habituelle

• Forme spéciale

double (*p1)(double, double) = min;double (*p2)(double, double) = max;NOM p1 = min, p2 = max;

Page 194: C2 - Langage C - ISIMA 1 - Deuxieme partie

C & UNIX

1. Processus2. Interface3. Entrées/sorties de bas niveau

Page 195: C2 - Langage C - ISIMA 1 - Deuxieme partie

195

Processus

• Identifiant unique processus identifier Type spécial pid_t

• Processus père (sauf processus 0)

pid_t getppid();

pid_t getpid();

$ echo $$ (shell)

Page 196: C2 - Langage C - ISIMA 1 - Deuxieme partie

196

Copie de processus (1)

• Création d'un processus fils, copie conforme du processus père Même zone de données et de code Même environnement Même priorité Même description de fichiers

• Exécution concurrente des deux processus

Page 197: C2 - Langage C - ISIMA 1 - Deuxieme partie

197

Copie de processus (2)

Valeur de retour :-1 : erreur lors de la création

limite du nombre de processus 0: processus fils>0 : processus père, pid du processus fils

Après un fork(), tout se passe comme si chacun venait de faire un fork()

pid_t fork(); #include <unistd.h>

Page 198: C2 - Langage C - ISIMA 1 - Deuxieme partie

198

Terminaison de processus

• Terminaison "normale" Fin de la fonction main() Fonction

• Valeur transmise au shell Retour du main() Paramètre d'exit()

void exit(int);

0 : fin normale

$ echo $? (shell [k]sh)> print ERRORLEVEL (dos/win)

Page 199: C2 - Langage C - ISIMA 1 - Deuxieme partie

199

exit()

• Définie dans

• Sortie propre du programme Tampons vidés Fichiers fermés

• Libérer la mémoire allouée sur le tas

#include <stdlib.h>

ptr = malloc(…);if (!ptr) exit(2);

Page 200: C2 - Langage C - ISIMA 1 - Deuxieme partie

200

#include <stdio.h>#include <unistd.h>void main() {  pid_t pid;  switch(pid=fork()) {    case (pid_t) -1 : printf("Erreur");      exit(2);     case (pid_t) 0 : /* sleep(100); */      printf("FILS: %d (PERE: %d)", getpid(), getppid());       exit(0);     default : printf("PERE:%d (PÈRE: %d)", getpid(), getppid()); }

Exemple 1

Page 201: C2 - Langage C - ISIMA 1 - Deuxieme partie

201

int i;for (i = 0; i < 3; i++) fork();

Exemple 2

• Combien de processus sont créés ?

Page 202: C2 - Langage C - ISIMA 1 - Deuxieme partie

202

Interface C / Système

• Faire un appel système

• Passer des paramètres (ligne de commande)

• Flux standards

int system(char *);

int main(int, char **);

system("ls –l");system("date");

stdin : entrée standard <stdout : sortie standard >stderr : sortie d'erreur standard 2>

Page 203: C2 - Langage C - ISIMA 1 - Deuxieme partie

203

Bibliographie

• La programmation sous UNIX, Jean-Marie RIFFLET, Ediscience, 2003

• The C Programming Language, KERNIGHAN, RITCHIE, Prentice-Hall, 1989

• Système X Window, la bible du programmeur Xlib, Albert JANSSENS, Eyrolles, 1993