Un survol du language C.

Slides:



Advertisements
Présentations similaires
Premier programme en C :
Advertisements

La boucle for : init7.c et init71.c
Introduction au Langage C,C++
Introduction Langage très répandu Noyau Linux VLC … Des avantages indéniables mais aussi des contraintes ! Ceci nest quun rapide tour.
Rappels C.
Formation C débutant. Notion de compilation source.c executable Phase de compilation Fichier de texte brut, inexploitable directement par la machine Fichier.
DECLARATION DE VARIABLES
Algorithmique Résume.
GEF 243B Programmation informatique appliquée Expressions et opérateurs §
GEF 243B Programmation informatique appliquée Expressions et opérateurs.
C.
FLSI602 Génie Informatique et Réseaux
Les bases de l’Algorithmique
Cours de C GTR 2003/ COURS DE PROGRAMMATION EN LANGAGE C ALBERT Arnauld.
Semaine #1 INF155 par Frédérick Henri.
Points importants de la semaine Les types arithmétiques. Les opérateurs.
Langage C Révision.
CPI/BTS 2 Programmation Web Introduction au PHP
Points importants de la semaine Les boucles. Les types arithmétiques. Les opérateurs.
Mémoire périphérique Stockage primaire: Mémoire principale (RAM)
8PRO100 Éléments de programmation Comment faire prendre une décision à un ordinateur?
RESUMES Module II1 SOMMAIRE CYCLE 1 : Saisir – Afficher – Données
8PRO100 Éléments de programmation Allocation dynamique de la mémoire.
FICHIERS.
Bases de la programmation en C++ 1 Les enchaînementsdinstruction Séquentiels. Exécutions dinstructions les unes à la suite des autres. Instructions séparées.
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
IFT Structures de données
IFT1969 Programmation scientifique en C
Semaine #1 INF130 par Frédérick Henri.
Principes de programmation
IFT 6800 Atelier en Technologies d’information
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
8PRO107 Éléments de programmation
Les Fichiers.
La programmation en langage C
8PRO100 Éléments de programmation Les types composés.
COURS DE PROGRAMMATION ORIENTEE OBJET :
Les Opérateurs Ils régissent toutes les opérations ou transformations sur les valeurs des variables. Opérateur d'affectation Opérateurs arithmétiques Opérateurs.
L’essentiel du langage C
Introduction au C.
2.1 - Historique Chapitre 2 : Introduction au langage C++
Les pointeurs L'opérateur &.
Algorithmique Les structures Rappel L'enchaînement séquentiel
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
Les adresses des fonctions
1 FICHIERS. 2 Les Fichiers  Les "entrées-sorties conversationnelles" échangent des informations entre le programme et l'utilisateur.  Le terme de fichier.
SIF-1053 Architecture des ordinateurs
1 Structures des données. 2  Le tableau permettait de désigner sous un seul nom un ensemble de valeurs de même type, chacune d'entre elles étant repérée.
 Syntaxe du langage PHP
Module I3 algorithmique et programmation
Les types composés Les enregistrements.
B.Shishedjiev - Affectation1 Expressions et affectation Comment produire des nouvelles valeurs.
Les variables fichiers. Le type fichier On manipule les fichiers par l’intermédiaire de structures FILE décrites dans stdio.h FILE *monFichier; –Nom physique.
1. Spoon Christophe Delagarde, septembre 1998 I.U.T., Université de la Méditerrainée 2.
Les entrées-sorties élémentaires
Langage de programmation
Les expressions. Une expression retourne une valeur lorsqu’elle est exécutée par le programme. a+2, x==0, i++, !isdigit(c) && b, sin(Pi),… On peut donc.
Scripts et fonctions Instructions de contrôle
PRO-1027 Programmation Scientifique en C
pour les programmeurs en C++ Java 2 Part 1 3 Histoire de Java Projet de connexion des machines: 1991 Le nom Java a été introduit dans un café Développé.
Introduction à l’utilitaire
Philippe Gandy - 8 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Objets et Actions Élémentaires.
Algorithmique et langage C
Introduction au langage C
Informatique 2A Langage C 1 ère séance.
ALGORITHME ET PROGRAMMATION RÉVISION Informatique et Sciences du Numérique.
Informatique 2A Langage C 4ème séance
A quoi sert la programmation? - indispensable pour plusieurs métiers. - passion. But du cours: - suite du cours Prog. Imp. I - fichiers, pointeurs, modularité.
Transcription de la présentation:

Un survol du language C

Le language C Language impératif: Un programme est vu comme une séquence d’instructions. Chaque instruction produit une transformation de l'état du programme (mémoire). Langage procédural: Basé sur le concept de d'appels de fonctions (procédures, sous-routines). Chaque fonction est une séquence d'instructions et peut être appelée à partir de n'importe quelle autres fonctions (y compris elle même).

Les types de données Toutes les valeurs en C sont du type réel ou entier. En fait il s’agit de deux « familles » de types puisqu’il existe plusieurs sortes d'entiers et de réels. Voici les principaux types en C. char: 8 bits short int: longueur des mots machines (souvent 32 bits) long float: simple précision (souvent 32 bits) double: double précision (souvent 64 bits) long double François Lemieux, 2006

Les constantes Les constantes de type double. Les constantes de type int. décimales: 17 8 -68 octales: 021 010 -0104 (commence par un zéro) hexadécimales: 0x11 0X8 -0x44 (commence par 0x ou 0X) Les constantes de type double. point flottant: 1200.0 3.1416 -.00067 avec exposant: 12e2 31416E-4 -67e-5 mixtes: 1.2e3 3.1416e0 -6.7E-4 François Lemieux, 2006

Déclaration des variables La déclaration des variables se fait selon le modèle suivant: type variable1, variable2, ... ; Remarquez la virgule séparant deux variables ainsi que le point-virgule à la fin. Exemples: int nbre; définit nbre comme une variable entière int a,b,c; définit trois variables entières dont les noms respectifs sont a, b et c. double x[10]; x est un tableau de 10 réels François Lemieux, 2006

Les opérateurs arithmétiques } + addition - soustraction * multiplication / division % opérateur de modulo Donne un int si les deux opérandes sont de type int, donne un double sinon } Ne s'applique qu'à des opérandes de type int. Donne un int. Exemple: 4 % 3 vaut 1 12 % 3 vaut 0 17 % 5 vaut 2 donne le reste de la division entière François Lemieux, 2006

Les opérateurs de comparaisons type d'opérateur notation mathématique notation en C égal plus grand plus grand ou égal plus petit plus petit ou égal différent = > ³ < £ ¹ = = > > = < < = ! = François Lemieux, 2006

Les opérateurs logiques Type d’opérateur Notation en C ET OU NON && || ! François Lemieux, 2006

La priorité des opérateurs en C Opérateurs Associativité ( ) de gauche à droite ! de droite à gauche * / de gauche à droite + - de gauche à droite < <= > >= de gauche à droite == != de gauche à droite && de gauche à droite || de gauche à droite = de droite à gauche François Lemieux, 2006

Les instructions En C, une instruction est simple ou composée (dans ce dernier cas on parle aussi d'un bloc d'instructions). Instructions simples: Ex. x = x + 1; y = cos(x); x = cos(x / y - 8) * 2; Blocs d'instructions: Ex. { x = x + 1; } 3 instructions simples 1 bloc d’instructions

Instruction conditionnelle Forme 1 if (expression) then instruction L'instruction est évaluée si et seulement si la valeur de l'expression est différente de 0. = 0  FAUX  0  VRAI Expression

Instruction conditionnelle Forme 2 if (expression) then instruction else La première instruction est évaluée si la valeur de l'expression est différente de 0, sinon la seconde instruction est évaluée.

Instruction conditionnelle Forme 3 if (expression) then instruction else if (expression) then else

Autre forme conditionnelle switch (expression) { case expression-constante: instruction default: instructions } L'expression doit être de type entier. Elle est d'abord évaluée puis l'instruction correspondante est exécutée ainsi que les instructions suivantes.

Autre forme conditionnelle switch (expression) { case expression-constante: instruction default: instructions } L'expression doit être de type entier. Elle est d'abord évaluée puis l'instruction correspondante est exécutée ainsi que les instructions suivantes. valide: 5 2*3 + 5 non valide: 3*x + 5 x

Pour sortir d'un switch sans exécuter toutes les instructions, L'instruction break Pour sortir d'un switch sans exécuter toutes les instructions, on peut utiliser l'instruction break. Le break peut aussi être utilisé pour sortir des boucles.

Exemple switch (n) { case 0: printf(“0”); case 1: printf(“1”); default: printf(“3”);} Si n vaut 1 alors le programme affichera simplement: 123

Exemple switch (n) { case 0: {printf(“0”); break;} default: printf(“3”); } Si n vaut 1 alors le programme affichera simplement: 1

L'opérateur conditionnel “?:” expression1 ? expression2 : expresion3 expression1 est d'abord évaluée. Si sa valeur est différente de 0 alors expression2 est évaluéee. Sinon, expression3 est évaluée. La valeur d'une expression conditionnelle est égale à la valeur de l'expression qui est évaluée (expression2 ou expression3). Le type d'une expression conditionnelle est le type le plus général entre celui de expression2 et expression3. Donc le type est double si une des deux expression est de type double.

L'opérateur conditionnel “?:” Exemple: z = (x<5) ? 1 : 2 (x<5) ? y : z = 0

La boucle while while (expression) instruction Exemple. Pour afficher les 100 premiers entiers positifs: int compteur; compteur = 0; while (compteur < 100){ compteur + +; printf(“%d”, compteur); } François Lemieux, 2006

do instruction1 while (expression2) La boucle do-while do instruction1 while (expression2) Équivalent à: instruction1 while (instruction2) instruction1 Exemple. Pour lire et afficher une liste de nombre se terminant par 0. int n; do{ scanf(“%d”, &n); printf(“%d”, n); } while (n !=0) François Lemieux, 2006

for (expression1 ; expression2 ; expression3) instruction La boucle for for (expression1 ; expression2 ; expression3) instruction Équivalent à: expression1; while(expression2) { instruction expression3; } Exemple. Pour afficher les n premiers entiers positifs pairs: int i; for (i=2; i<=2*n; i=i+2) printf(“%d ”, i); François Lemieux, 2006

La bibliothèque standard du C Il y a peu d'opérateurs arithmétiques en C, mais à partir de ceux que nous avons vus il est possible d'en construire d'autres. On distingue les opérateurs de base des opérateurs complexe, construits à partir des opérateurs de base, en appelant ces derniers  fonctions. La plupart des environnements supportants le C standard disposent d'une large collection de fonctions appelée bibliothèque standard. François Lemieux, 2006

#include <math.h> Exemple: math.h Plusieurs fonctions mathématiques courantes font partie de la bibliothèque standard. Pour les utiliser il suffit d'inclure au début du programme la ligne suivante: #include <math.h> Il est alors possible d'employer des fonctions telles que: cos(x) cosinus de x pow(x,y) x à la puissance y sqrt(x) racine carrée de x ldexp(x,n) et plusieurs autres. François Lemieux, 2006

Exemple: ldexp(x,n) Examinons plus en détails la fonction ldexp. Nous savons que cette fonction retourne la valeur Considérons quelques exemples: ldexp(1 , 1) retourne ldexp(1.1, 1) retourne ldexp(1, 1.1) retourne Pourquoi??? François Lemieux, 2006

Exemple: ldexp(x,n) Pour comprendre ce qui se passe il faut savoir que la fonction ldexp attend deux nombres en entrée: x et n. x doit être un double n doit être un entier la fonction retourne un double Donc lorsque l'on exécute ldexp(1, 1.1), la fonction reçoit en fait les valeurs 1 et 1 puisque la partie fractionnaire du second opérande est tronquée. François Lemieux, 2006

Les prototypes de fonctions Morale: avant d'utiliser une fonction de la bibliothèque il faut connaître son prototype. Le prototype d'une fonction indique le nom de la fonction le type des paramètres le type de la valeur de retour Exemple: double ldexp(double, int) indique que ldexp est une fonction à deux paramètres (un double et un int) qui retourne un double. François Lemieux, 2006

double pow(double x, double y) Exemple: pow(x,y) La fonction d'exponentiation a le prototype suivant: double pow(double x, double y) de sorte qu'on ne peut pas l'utiliser de la façon suivante: pow(2, 3) % 5 Question: Pourquoi? François Lemieux, 2006

Exemple: pow(x,y) Il faut plutot écrire: (int) pow(2, 3) % 5 ou encore L'opérateur cast permet de convertir le type d'une expression en un autre type. (type) expression François Lemieux, 2006

{ { Définition des fonctions Dans la plupart des langages de programmation, la définition d'une fonction comporte deux parties: l'en-tête et le corps. { Nom de la fonction Type de la valeur retournée Nom des paramètres Types des paramètres En-tête { Déclaration des variables Instructions Corps François Lemieux, 2006

Les paramètres Paramètres formels: Ceux utilisés dans la définition. Paramètres d'appel: Ceux utilisés lors de l'appel. François Lemieux, 2006

Passage des paramètres Par copie seulement: Les paramètres d'appel sont copiés dans les paramètres formels: création de nouvelles variables. Les tableaux ne sont pas passés par copie. On utilise plutôt les pointeurs: seul l'adresse du tableau est copiée. François Lemieux, 2006

L'appel de fonctions Créations de nouvelles variables pour chacun des paramètres passés par copie. Le contrôle est donné à la fonction: la première ligne du corps de la fonction est d'abord exécutée. Remarques: Le nom des variables déclarées dans une fonctions est local à cette fonction et il est invisible aux autres fonctions. Deux fonctions distinctes peuvent utiliser le même identificateur pour nommer deux cases mémoire distinctes. François Lemieux, 2006

Retour d'une fonction À l'intérieur d'une fonction, l'instruction return expression; est exécutée de la façon suivante: L'expression est d'abord évaluée. Le résultat est retourné à la fonction appelante Toutes les variables ayant été créées après l'appel de la fonction sont détruites. Le contrôle est redonné à la fonction appelante. François Lemieux, 2006

Concepts importants Utilisations des fonctions pour étendre les possibilités de l'ordinateur. Prototype d'une fonction Définition d'une fonction. Les paramètres L'appel d'une fonction Le retour d'une fonction François Lemieux, 2006

Structure d'un programme en C Un programme en C est une collection de fonctions qui interagissent entre elles afin d'exécuter un calcul. Une des fonctions doit porter le nom main: c'est la première fonction à être appelée lors de l'exécution du programme. Comme on l'a vu, on peut utiliser les fonctions de la bibliothèque standard ou encore, on peut définir nos propres fonctions François Lemieux, 2006

La récursion Il est possible pour une fonction donnée d'appeler une autre fonction. Que se passe-t-il si une fonction s'appelle elle-même? C'est ce que l'on appelle la récursion. François Lemieux, 2006

Exemple Appel à factoriel(4) int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); nfact int n, nfact; int factoriel (int n){ if (n £ 1) return 1; return n * factoriel(n-1); } . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else 4 int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); nfact scanf("%d", &n); . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else 4 int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); nfact if (n < 0) printf(“entrée négative: %d\n”, n); . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else 4 int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); nfact nfact = factoriel(n); . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 if (n £ 1) return 1 return n * factoriel(n-1); . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 if (n £ 1) return 1 retutn n * factoriel(n-1); return n * factoriel(n-1) . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 return n * factoriel(n-1); . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 retutn n * factoriel(n-1); return n * factoriel(n-1) . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1); n 2 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 return n * factoriel(n-1); . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1); n 2 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1); n 2 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 retutn n * factoriel(n-1); . . return n * factoriel(n-1) François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1); n 2 n 1 if (n £ 1) return 1 return n * factoriel(n-1); if (n £ 1) return 1 return n * factoriel(n-1) . . if (n £ 1) return 1 return n * factoriel(n-1) François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 3 if (n £ 1) return 1 return n * factoriel(n-1) n n 2 n 1 if (n £ 1) return 1 return n * factoriel(n-1) if (n £ 1) return 1 return n * factoriel(n-1) . . if (n £ 1) return 1 si (n £ 1) retourner 1 return n * factoriel(n-1) François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1) n 2 if (n £ 1) return 1 return n * factoriel(n-1) if (n £ 1) return 1 retourner n *1 . . return n * 1 François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 n 3 if (n £ 1) return 1 return n * factoriel(n-1) if (n £ 1) return 1 retourner n * factoriel(n-1) return n * 2 . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact n 4 if (n £ 1) return 1 retourner n * factoriel(n-1) return n * 6 . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact ¬24 nfact 24 . . François Lemieux, 2006

if (n < 0) printf(“entrée négative: %d\n”, n); else int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact 24 printf(“la factorielle de n est %d\n”, nfact); . . François Lemieux, 2006

est 24 La factorielle de 4 est 24 int n, nfact; scanf("%d", &n); if (n < 0) printf(“entrée négative: %d\n”, n); else nfact = factoriel(n); printf(“la factorielle de n est %d\n”, nfact); n 4 nfact 24 est 24 La factorielle de 4 est 24 . . François Lemieux, 2006

À retenir Sans condition d'arrêt, l'exécution de la Une fonction peut s'appeler elle-même Sans condition d'arrêt, l'exécution de la fonction n'aurait pas de fin. François Lemieux, 2006

Les adresses Les cases mémoires ont toutes un numéro qui les distingue les unes des autres: ce numéro est appelé adresse. C’est par cette adresse que le processeur peut communiquer avec la mémoire. 1 2 3 4 . . max François Lemieux, 2006

Les adresses et les variables Le nom que l’on donne au cases mémoire est traduit en une adresse juste avant l’exécution d’un programme. Cela est nécessaire afin que le processeur sache à quelle case mémoire est associée chaque variable. En général il est impossible de prévoir à quelle adresse sera placée une variable. Le nom des variables est donc nécessaire. c1: 1 char c1 = c2; Lire le contenu de la case 3. Mettre ce qui a été lu dans la case 1. 2 c2: 3 1324 char 4 . . max François Lemieux, 2006

Le partage de la mémoire Sur les systèmes modernes il peut y avoir plusieurs usagers se partageant la mémoire et chaque usager peut exécuter plusieurs programmes simultanément. Cela signifie que l’on n’est pas libre d’utiliser toutes les cases mémoires comme on le veut. Une case peut être occupée par un programme à un certain moment et libre à un autre. Cette situation est aléatoire. Pour cette raison, on ne mentionne jamais explicitement une adresse dans un programme même si cela est théoriquement possible. François Lemieux, 2006

Adresses valides et non valides Exemple. Dans le pseudo-code suivant: Lire le contenu de la case 3. Mettre ce qui a été lu dans la case 1. Que se passe t-il si au moment de l’exécution la case mémoire 1 est déja utilisée par un autre programme. La case est alors non valide et il y aura erreur à l’exécution. C’est pour cette raison que l’on utilise des variables. Avant l’exécution, une adresse valide est associée à chaque variable. Seul notre programme pourra utiliser ces cases mémoire. François Lemieux, 2006

Position des variables dans la mémoire int . . Sauf pour les tableaux, il n’y a aucune garantie que les variables occupent des cases adjacentes en mémoire. Exemple. int a,b[4],c,d[3]; b[0] int b[1] int b[2] int b[3] int int c . . d[0] int d[1] int d[2] int . . François Lemieux, 2006

Les adresses et les tableaux Le nom d’un tableau correspond à l’adresse du début du tableau. Exemple: char tab[5]; printf(“%p\n”, tab); 4027630992 printf(“%p\n”, tab+1); 4027630993 printf(“%p\n”, tab+2); 4027630994 Note: ‘%p’ sert à afficher les adresses. François Lemieux, 2006

Les tableaux d’entiers Exemple: int tab[5]; printf(“%p\n”, tab); 4027630976 printf(“%p\n”, tab+1); 4027630980 printf(“%p\n”, tab+2); 4027630984 Question: Pourquoi? +4 +4 François Lemieux, 2006

L’incrémentation d’une adresse L’adresse 16220 n’est pas valide a: 16216 int . . b[0]: b=24600 int b[1]: b+1=24604 int Incrémenter une adresse ne veux pas dire ajouter 1, cela veut dire aller à l’adresse suivant la variable courante. En général cela n’est utile que si on est dans un tableau. b[2]: b+2=24608 int b[3]: b+3=24612 int . . d[0]: d=54316 char d[1]: d+1=54317 char d[2]: d+2=54318 char . . François Lemieux, 2006

Remarque Si Tab est un tableau alors L’adresse de Tab[0] est Tab, etc. Cela est vrai quelque soit le type des éléments de Tab. François Lemieux, 2006

L’opérateur & Il est possible de connaître, pendant l’exécution d’un programme, l’adresse associée à une variable. En C, cela est possible à l’aide de l’opérateur unaire & Exemple: char c; int n, tab[1000]; L’adresse de c est &c L’adresse de n est &n L’adresse de tab[3] est &tab[3] ou tab+3 François Lemieux, 2006

L’opérateur * Il est aussi possible de connaître, pendant l’exécution d’un programme, le contenu de la case mémoire située à une adresse donnée. En C, cela est possible à l’aide de l’opérateur unaire * Exemple: char c; int tab[1000]; Le contenu de l’adresse tab + 25 est *(tab + 25) *(tab + 25) est donc identique à tab[25] *(&c) est identique à c *c n’a aucun sens François Lemieux, 2006

Exemple Les expressions logiques suivantes sont vraies: &n == 12556 *(12560) == 60 *(12560) < c2 *(&r) == 12.345 . . n: 12556 5000000 int c1: 12560 60 char c2: 12561 61 char r: 12562 12.345 double . . François Lemieux, 2006

Résumé des opérations sur les adresses On peut: Additionner une adresse et un entier Déterminer l’adresse d’une variable Déterminer le contenu d’une adresse On ne peut pas Additionner deux adresses (mais on peut soustraire deux adresses d’un même tableau) François Lemieux, 2006

Les pointeurs Un pointeur est une variable pouvant contenir une adresse. Exemple: int *pn; pointeur sur une valeur entière char *pc; pointeur sur un caractère double *pr; pointeur sur un double François Lemieux, 2006

Les pointeurs et les tableaux En C les pointeurs sont intimement liés aux tableaux. Exemple: int tab[10], *p; p=tab; tab[3] = 70; *(tab + 3) = 70; p[3] = 70; *(p + 3) = 70; tous équivalent: François Lemieux, 2006

Remarque Le nom d’un tableau est une adresse constante et non pas un pointeur qui est une variable. Exemple: int tab[10], *p; p=tab; p = tab; /* Valide */ tab = p; /* Non valide */ 1 2 3 4 5 6 7 8 9 10 tab: p: François Lemieux, 2006

Quelques utilités des pointeurs Pour implémenter le passage de paramètres par référence Pour implémenter le passage de tableaux en paramètre Pour utiliser des indices négatifs au tableaux Fondamental en structure de données François Lemieux, 2006

Le pointeur NULL Il est parfois utile d'indiquer qu'un pointeur ne contient aucune adresse. On utilise alors le pointeur NULL dont la valeur est 0. Exemple: int *p; p=NULL; M if (p != NULL) printf("%d",*p); François Lemieux, 2006

Les tableaux à deux dimensions Exemple: int Tab[N][M] L’adresse de Tab[i][j] est &Tab[0][0] + i*M + j . . Tab[0][0] = &Tab[0][0] int Exemple avec N=3 et M=2 Tab[0][1] = &Tab[0][0] + 1 int Tab[1][0] = &Tab[0][0] + 2 int Tab[1][1] = &Tab[0][0] + 3 int Tab[2][0] = &Tab[0][0] + 4 int Tab[2][1] = &Tab[0][0] + 5 int . . . . François Lemieux, 2006

Les tableaux à deux dimensions Exemple: int Tab[N][M] L’adresse de Tab[i][j] est &Tab[0][0] + i*M + j Remarque: Pour calculer l’adresse de Tab[i][j] il n’est pas nécessaire de connaître N mais il est essentiel de connaître M Cela explique pourquoi on doit préciser M dans les paramètres formels. Ex. f(char tab[N][M]) ou f(char tab[][M]) François Lemieux, 2006

Les constantes de type caractère En C une constante de type caractère est un nombre entier écrit sous la forme d'un caractère entre apostrophes, comme ‘a’. La valeur d'une constante de type caractère est égale à la valeur du caractère d'après le jeu de caractère de la machine (ex. ASCII). Exemples: ‘a’ vaut 97 ‘A’ vaut 65 ‘B’ vaut 66 ‘0’ vaut 48 François Lemieux, 2006

Les séquences d'échappement ‘\a’ caractère d'alerte (sonnerie, bell) ‘\b’ retour en arrière (backspace) ‘\f’ saut de page (formfeed) ‘\n’ fin de ligne (newline) ‘\r’ retour de chariot (carriage return) ‘\t’ tabulation horizontale ‘\v’ tabulation verticale ‘\\’ backslash ‘\?’ point d'interrogation ‘\’’ apostrophe ‘\” ’ guillemet ‘\ooo’ nombre octal ‘\xhh’ nombre hexadécimale François Lemieux, 2006

Les variables de type caractère En C, les caractères sont des entiers de 8 bits. Pour déclarer une variable de type caractère, on procède de la façon suivante: char c1; /* c1 est une variable de type caractère */ char c2 = ‘a’; /* c2 est une variable de type caractère initialisée à 97 */ char c3 = 97; /* c3 et c2 contiennent la même valeur */ François Lemieux, 2006

Exemple Pourquoi un int? #include <stdio.h> /* copie l’entrée sur la sortie; première version*/ main(){ int c; c = getchar(); while (c != EOF) { putchar(c); } Pourquoi un int? François Lemieux, 2006

Exemple La valeur retourné par getchar() peut être un des 256 caractères ASCII OU la valeur EOF La fonction getchar() peut donc retourner 257 valeur possibles. Mais un char est un entier de 8 bits et ne peut donc représenter que 256 valeurs possibles. On doit donc utiliser plus de bits (et donc un int) pour faire la différence entre un caractère et EOF. François Lemieux, 2006

Exemple Exemple: Sur un Pentium III, un int est un entier de 32 bits et EOF s’écrit en binaire de la façon suivante: 11111111111111111111111111111111 32 bits Losrque l’on met EOF dans une variable de type char on ne met que les 8 premiers bits, c’est-à-dire 11111111 = 255 Le caractère dont la valeur est 255 peut être ÿ ou encore le caractère blanc selon le jeu de caractères utilisé. François Lemieux, 2006

Exemple #include <stdio.h> /* copie l’entrée sur la sortie, seconde version */ main(){ int c; while ((c=getchar()) != EOF) putchar(c); } François Lemieux, 2006

Les constantes de type chaîne Un constante de type chaîne est une séquence de caractères, éventuellement vide, placée entre guillemets. Exemple: “Je suis une chaîne ” “Bonjour groupe!\n” “Comment allez-vous\?\n” Note: Les guillemets ne font pas partie de la chaîne. François Lemieux, 2006

Les chaînes de caractères En C il n’y a pas de variable de type chaîne de caractères. Une chaîne de caractère est un tableau de caractères se terminant par le caractère \0 (le caractère NUL ayant la valeur 0) Ainsi la chaîne “Bonjour groupe!” serait représentée de la façon suivante: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 B o n j o u r g r o u p e ! \0 François Lemieux, 2006

Déclarer un tableau de caractères Les 4 déclarations suivantes ont le même effet: char chaine[]={'B','o','n','j','o','u','r',' ','g','r','o','u','p','e','!','\0'}; char chaine[16]={'B','o','n','j','o','u','r',' ','g','r','o','u','p','e','!','\0'}; char chaine[]="Bonjour groupe!"; char chaine[16]="Bonjour groupe!"; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 B o n j o u r g r o u p e ! \0 François Lemieux, 2006

Affectation L'opération suivante est illégale: char chaine[16]; chaine="Bonjour groupe!"; On ne peut pas affecter de façon dynamique une chaine à un tableau de caractères. François Lemieux, 2006

Types composés En plus des types de base (entier, réels, charactères, etc) il est possible dans la plupart des langages de programmation de définir ses propres types. Il s’agit en fait de rassembler une ou plusieurs variables, qui peuvent être de types différents, et de les regrouper sous un seul nom afin de les manipuler plus facilement. François Lemieux, 2006

Exemple en C struct complexe { /* défini un nouveau type */ double reel; double imag; }; struct complexe x; /* déclare une variable de type complexe */ x.reel: x.imag: François Lemieux, 2006

Où définir un nouveau type Si on défini un nouveau type à l’intérieur d’une fonction alors il ne sera visible qu’à l’intérieur de cette fonction. Pour qu’un type composé soit visible dans toutes les fonctions d’un fichier, il faut le déclarer au début du fichier, à l’extérieur de toute fonction. Note: La même chose s’applique à la déclaration de variables: c’est ce que l’on appelle les variables globales. #include <stdio.h> struct complexe { double reel; double imag; };  fonction(...){ struct complexe x; } François Lemieux, 2006

Déclarer une structure struct complexe { double reel; double imag; }; struct complexe x={5,3}; 5 x.reel: 3 x.imag: François Lemieux, 2006

Accéder aux membres d’une structure struct complexe x, y, z; x.reel = 5; x.imag = 3; y = x; z.reel = x.réel; z.imag = 8; 5 x.reel: 3 x.imag:  5 y.reel: 3 y.imag:  5 z.reel: 8 z.imag: François Lemieux, 2006

Comparer deux structures 5 x.reel: if (x == y) printf(“Deux structures égales”); if (x != z) printf(“Deux structures differentes”); 3 x.imag:  5 y.reel: 3 y.imag:  5 z.reel: 8 z.imag: Remarque: La comparaison x<y n'est pas valide car elle n'a aucun sens à priori. François Lemieux, 2006

Les structures et les fonctions On peut passer des structures en paramètre. On peut utiliser les structures comme valeur de retour. Contrairement aux tableaux, les structures sont passées par copie. François Lemieux, 2006

typedef Dans l’exemple précédent, il est laborieux d’avoir à écrire autant de struct complexe. Le C fournit une fonctionnalité appelée typedef servant à créer des noms de nouveaux types de données. Exemple: typedef struct complexe Complexe Complexe x, y; Le nom Complexe devient synonyme de struct complexe François Lemieux, 2006

Les structures et les pointeurs Les pointeurs de structures sont si fréquemment utilisés qu’il existe une notation abrégée. Exemple: struct complexe *pc, x; pc = &x; pc->reel = 3; /* identique à (*pc).reel=3 */ pc->imag = 5; /* identique à (*pc).imag=5 */ François Lemieux, 2006

Allocation dynamique de la mémoire Jusqu’à maintenant, toute la mémoire que nous avons utilisée dans nos programmes devait avoir été allouée avant l'exécution à l’aide des déclarations de variables. Il est parfois utile d’allouer une partie de l’espace mémoire en cours d’exécution. François Lemieux, 2006

Exemple Par exemple si on a besoin de mémoriser un certains nombre d’objets mais que ce nombre n’est pas connu avant l’exécution du programme. Il faut alors allouer suffisament d’espace au cas ou le nombre d’objets est grand. Si le nombre d’objets est petits, on gaspille inutilement de l’espace mémoire. François Lemieux, 2006

Le fichier d’entête stdlib.h Le fichier d’entête stdlib.h contient des déclarations de fonctions traitant, entre autres, de l’allocation de la mémoire: - malloc - free - calloc - realloc François Lemieux, 2006

void *malloc(size_t size) size_t est le type d’entiers positifs retourné par l’opérateur sizeof malloc retourne un pointeur sur un espace mémoire réservé à 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. François Lemieux, 2006

Pointeurs sur void La fonction malloc ne sait pas à quoi servira l’espace mémoire qui lui est demandée. Elle ne sait pas quel type d’objet utilisera cet espace. Alors, elle retourne un pointeur générique qui peut être converti en n’inporte quel type de pointeur: un pointeur sur void François Lemieux, 2006

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 malloc, calloc ou realloc. François Lemieux, 2006

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 pas être satisfaite. La mémoire allouée est initialisée par des zéros. François Lemieux, 2006

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, le contenu de l’objet est conservé, et l’espace mémoire supplémentaire n’est pas initialisé. realloc retourne un pointeur sur un nouvel espace mémoire, ou bien NULL si cette demande ne peut pas être satisfaite, auquel cas *p n’est pas modifié. François Lemieux, 2006

Exemple On veut lire des entiers et les mettre en mémoire. Plutôt que de créer un tableau avant l’exécution, on utilise calloc pendant l’exécution. int *p, n; scanf(“%d”, &n); p = (int *) calloc(n, sizeof(int)); si plus tard cet espace n’est plus suffisant, alors on utilise: p = (int *) realloc(p, 2*n); … p: François Lemieux, 2006

Exemple Liste chaînée struct noeud{ int valeur; noeud *suivant; }; struct noeud *chaine, *p; chaine: p: François Lemieux, 2006

Exemple 5 chaine = (struct noeud*) malloc(sizeof(struct noeud)); valeur suivant chaine: p: François Lemieux, 2006

Exemple 5 chaine = (struct noeud*) malloc(sizeof(struct noeud)); chaine -> valeur = 8; chaine: 8 p: François Lemieux, 2006

Exemple 5 chaine -> suivant = (struct noeud*) malloc(sizeof(struct noeud)); chaine: 8 p: François Lemieux, 2006

Exemple 5 p = chaine -> suivant; 8 chaine: p: François Lemieux, 2006

Exemple 5 p -> valeur = 5; chaine: 8 5 p: François Lemieux, 2006

Exemple 5 p -> suivant = (struct noeud*) malloc(sizeof(struct noeud)); chaine: 8 5 p: François Lemieux, 2006

Exemple 5 p = p -> suivant; chaine: 8 5 p: François Lemieux, 2006

Exemple 5 p -> valeur = 13; p -> suivant = NULL; 8 5 13 chaine: p: François Lemieux, 2006

Exemple 5 p = chaine; while (p != NULL){ printf(“%d\n”, p->valeur); p = p->suivant; } chaine: 8 5 13 p: François Lemieux, 2006

Les fichiers FILE *fopen(char *nom, char *mode) int fclose(FILE fp); retourne NULL si une erreur se produit. int fclose(FILE fp); modes: "r" : lecture "w" : écriture "a" : ajout 3 pointeurs de fichiers particuliers: stdin, stdout, stderr

Opérations sur les fichiers int getc(FILE *fp) int putc(int c, FILE *fp) int fscanf(FILE *fp, char *format, ...) int fprintf(FILE *fp, char *format, ...) int fseek(FILE *fp, long deplacement, int origine) SEEK_SET : début du fichier SEEK_CUR : position courante SEEK_END : fin du fichier int feof(FILE *fp)

Exemple Copier un fichier dans un autre FILE * fp1=fopen("fichier1", "r"); FILE * fp2=fopen("fichier2", "a"); while (!feof(fp)) { fputc(fgetc(fp),fp2); } fclose(fp); fclose(fp2);