Chapitre 3. Introduction au langage C Quelques propriétés du langage C : utilisation intensive des fonctions ; au début, langage faiblement typé (au contraire de Pascal) ; C est un langage structuré ; une programmation de bas niveaux est possible (manipulation de bits) utilisation intensive des pointeurs. Pourquoi C est-il devenu un langage largement utilisé? il possède des constructions de haut niveau ; il est possible de développer des programmes très proches de la machine ; le langage C produit des programmes efficaces ; des compilateurs existent pour un grand nombre de machines. M. KRAJECKI 1 DESS IAS Année 2003-2004 1. Type, variables et affectation Un mot mémoire est une suite de chiffres en binaire (0 ou 1). Il est composé d un nombre fixe de bits (par exemple 8, 16, 32 ou 64). Une suite de 8 bits est appelé un octet ou byte. Un type définit une méthode d interprétation d un mot mémoire. Par exemple, le type entier permet une représentation binaire des nombres entiers et le type caractère, une représentation binaire d un caractère. Le nombre de mots mémoire associés à chaque type est dépendant de la version d UNIX utilisée, cependant le type char est pratiquement toujours codé sur un octet. M. KRAJECKI 2 DESS IAS Année 2003-2004
Types du langage C Les principaux types du langage C sont : int : les entiers signés ; unsigned int : les entiers non signés ; char : les caractères ; float : les réels ; double : les réels à double précision. Attention : il n existe pas en C de type booléen. C est à vous de le définir (à l aide du type caractère ou entier). Voici un petit programme C (stocké dans le fichier taille.c) vous permettant de connaître le nombre d octets utilisés pour coder chaque type élémentaire... M. KRAJECKI 3 DESS IAS Année 2003-2004 Un premier programme printf("char : %d\n", sizeof(char)) ; printf("int : %d\n", sizeof(int)) ; printf("float : %d\n", sizeof(float)) ; printf("double : %d\n", sizeof(double)) ; Il ne reste qu à le compiler et à l exécuter (sur PC avec Linux)... M. KRAJECKI 4 DESS IAS Année 2003-2004
Explications $ gcc taille.c $ a.out char : 1 int : 4 float : 4 double : 8 Donc le type double est codé sur 8 octets. Examinons plus en détail ce premier programme C : un programme C est un ensemble de fonctions ; ces fonctions peuvent éventuellement ne pas rendre de résultat ; elles sont définies dans un ou plusieurs fichiers source. M. KRAJECKI 5 DESS IAS Année 2003-2004 Explications Chaque fonction est constituée par une suite d instructions. Chaque instruction est terminée par ;. Il exite une fonction particulière, la fonction main() qui définit le point d entrée du programme. La fonction printf permet d afficher une chaîne de caractères sur la sortie standard. L instruction : printf("char : %d\n", sizeof(char)) ; demande l affichage de la chaîne de caractères "char : " suivie d un entier (%d) qui est passé en paramètre à la fonction printf (sizeof(char)). La fonction sizeof a pour résultat la taille mémoire en octets associée au paramètre qui peut être soit un type (char), soit une variable. M. KRAJECKI 6 DESS IAS Année 2003-2004
Variable et affectation Une variable est désignée par un nom et un type qui sont invariables au cours de l exécution du programme. À chaque variable est associée un ou plusieurs mots mémoire. L affectation permet de donner une valeur à une variable. Les deux paramètres de l affectation doivent avoir des types compatibles. Par exemple : a,b : entier int a, b ; a 5 a = 5 ; b a b = a ; M. KRAJECKI 7 DESS IAS Année 2003-2004 Opérateurs et négation Le test d égalité est effectué à l aide de l opérateur ==. Le résultat de cette opération est 1 si les 2 opérandes sont égales, 0 sinon. On peut également utiliser les différents opérateurs arithmétiques (+, -, *, /). Il existe des opérateurs de comparaison (<, >, <=, >=) ainsi que des opérateurs booléens et (&&), ou ( ), la négation (!). M. KRAJECKI 8 DESS IAS Année 2003-2004
Les pointeurs Il existe également en C, un type pointeur qui permet de désigner l adresse mémoire où est stockée une variable. Voici un cours exemple de son utilisation et son résultat : int a, b, *pa, *pb ; a = 5 ; b = 23 ; pa = &a ; /* pa contient l adresse mémoire où est stockée a */ M. KRAJECKI 9 DESS IAS Année 2003-2004 Les pointeurs (exemple) pb = &b ; printf("a= %d, pa = %d\n", a, pa) ; printf("b= %d, pb = %d\n", b, pb) ; pb = pa ; *pb = 10 ; /* le contenu de la variable désignée par pb prend la valeur 10 */ printf("après la modification :\n"); printf("a= %d, pa = %d\n", a, pa) ; printf("b= %d, pb = %d\n", b, pb) ; M. KRAJECKI 10 DESS IAS Année 2003-2004
2. Schémas itératifs Les conditionnelles : supposons, que nous ayons à écrire un algorithme qui a pour but la comparaison de 2 entiers. Cet algorithme se formule de la façon suivante. a, b, min : entier int a, b, min ; Si a<b alors if (a<b) { min a min = a ; Sinon else { min b min = b ; Fsi M. KRAJECKI 11 DESS IAS Année 2003-2004 Les conditionnelles (généralisation) Plus généralement, une conditionnelle s exprime ainsi : Si exp1 alors if (exp1) { suite-inst1 suite-inst1 ; SinonSi exp2 alors else if (exp2) { suite-inst2 suite-inst2 ;...... SinonSi expn-1 alors else if (expn-1) { suite-instn-1 suite-instn-1 ; SinonSi expn alors else if (expn) { suite-instn suite-instn ; Fsi M. KRAJECKI 12 DESS IAS Année 2003-2004
Exemple : résolution d un polynome du second degré #include <math.h> int a, b, c ; printf("résolution\n"); printf("valeur de a? ") ; scanf("%d", &a) ; printf("\n Valeur de b? ") ; scanf("%d", &b) ; printf("\n Valeur de c? ") ; scanf("%d", &c) ; printf("\n Racine de %d x^2 + %d x + %d :\n", a, b, c) ; M. KRAJECKI 13 DESS IAS Année 2003-2004 Résolution d un polynome du second degré (suite) if (a==0) if (b==0) if (c==0) printf("tout x est solution.\n"); else printf("pas de solution.\n"); else printf("%f est solution.\n", (float) c/b) ; else M. KRAJECKI 14 DESS IAS Année 2003-2004
Résolution d un polynome du second degré (suite) else { int delta = b*b -4*a*c ; if (delta < 0) printf("pas de solution réelle.\n") ; else if (delta == 0) printf("sol. double : %f.\n", (float)-b/(2*a)) ; else { float rac = sqrt(delta) ; printf("x1 = %f, x2 = %f.\n", (-b-rac)/(2*a), (-b+rac)/(2*a)); M. KRAJECKI 15 DESS IAS Année 2003-2004 Les boucles pour L itération bornée permet d exécution un nombre fixe de fois un bloc d instructions. Pour i de indmin à indmax faire for(i=indmin ; i<= indmax ; i=i+1){ suite_inst suite_inst ; Fpour Par exemple, pour calculer n!, voici un petit programme... M. KRAJECKI 16 DESS IAS Année 2003-2004
Remarques sur les boucles pour Quand on arrive à la fin de la boucle pour, la variable de contrôle est automatiquement incrémentée de, puis le programme teste si la borne supérieure est atteinte. Si non, on recommence les instructions qui sont dans la boucle avec la nouvelle valeur de la variable de contrôle. La variable de contrôle doit être de type scalaire (entier, caractère). La valeur de la variable est indeterminée à la fin d une boucle : défense de l utiliser à nouveau sans réinitialisation. M. KRAJECKI 17 DESS IAS Année 2003-2004 Calcul de n! int n, nb, produit = 1 ; printf("factorielle\n"); printf("n =? ") ; scanf("%d",&n) ; for(nb = 1 ; nb <= n ; nb++) produit = produit * nb ; printf("\n factorielle(%d) = %d\n", n, produit); M. KRAJECKI 18 DESS IAS Année 2003-2004
Itération non bornée Il existe en C une itération non bornée qui s exécute tant qu une condition de continuation (expression booléenne) est vérifiée. Tant que exp faire while(exp) { suite_inst ; suite_inst ; Ftantque Attention : si l expression booléenne est fausse la première fois, la suite d instructions n est pas exécutée. Par contre, si l expression est toujours vraie, une boucle infinie apparaît et le programme ne termine pas. M. KRAJECKI 19 DESS IAS Année 2003-2004 Exemple : calcul du PGCD de deux entiers int a, b ; printf("a = ") ; scanf("%d", &a); printf("\nb = "); scanf("%d", &b); while (a!= b) { if (a>b) a = a - b ; else b = b - a ; printf("\n PGCD = %d\n", a); M. KRAJECKI 20 DESS IAS Année 2003-2004
3. Définition de fonctions et procédures Une fonction est un bloc (une suite) d actions (d instructions), nommé et éventuellement paramétré permettant d obtenir un résultat. Une fonction est déclarée afin de pouvoir ensuite l appeler par son nom. On distingue trois types de paramètres : 1. paramètres en entrée (initialisés avant l appel à la fonction) ; 2. paramètres de sortie (calculés par la fonction) ; 3. paramètres en entrée et sortie (initialisés avant l appel et modifiés par la fonction). M. KRAJECKI 21 DESS IAS Année 2003-2004 Exemple : calcul du PGCD int pgcd(int a, int b) { while (a!= b) { if (a>b) a = a - b ; else b = b - a ; return(a) ; M. KRAJECKI 22 DESS IAS Année 2003-2004
Calcul du PGCD int u, v, p ; printf("a = ") ; scanf("%d", &u); printf("\nb = "); scanf("%d", &v); p = pgcd(u,v) ; printf("\n PGCD = %d\n", p); M. KRAJECKI 23 DESS IAS Année 2003-2004 Définition d une procédure Une procédure regroupe et nomme un ensemble d instructions éventuellement paramétré. Comme pour les fonctions, on distingue trois types de paramètres : en entrée, en sortie ou bien en entrée/sortie. Exemple : un nombre est dit parfait, s il est égal à la somme de ses diviseurs. Le premier nombre parfait est 6, car. Voici un programme en C qui affiche tous les nombres parfaits inférieurs à... M. KRAJECKI 24 DESS IAS Année 2003-2004
Les nombres parfaits void NombreParfait(int n){ int i, d, nb ; for(i=2; i<n; i++){ nb = 1 ; for(d=2; d<i; d++) if (i%d==0) nb+=d ; if (nb==i) printf("%d est un parfait\n", i); NombreParfait(100) ; M. KRAJECKI 25 DESS IAS Année 2003-2004 Passage de paramètres Nous avons déjà vu qu il existe trois types de paramètres : les paramètres en entrée, en sortie et en entrée/sortie. Les paramètres en entrée doivent être initialisés avant l appel de la fonction : si la fonction modifie ces paramètres, ces modifications seront perdues après l exécution de la fonction ; le compilateur C réalise dans ce cas un passage par valeur ; il alloue une variable temporaire pour chaque paramêtre en entrée et recopie sa valeur ; la fonction n aura alors pas accès directement au paramètre mais seulement à sa copie. M. KRAJECKI 26 DESS IAS Année 2003-2004
Les paramètres en sortie Les paramètres en sortie sont modifiés par l appel de fonction : pour que cette opération soit possible, il est nécessaire de fournir l adresse mémoire du paramètre en entrée ; la fonction doit être en mesure de modifier directement le paramètre ; c est pourquoi, les paramètres en sortie sont transmis en utilisant des pointeurs ; c est le même mécanisme qui est utilisé pour les paramètres en entrée/sortie. M. KRAJECKI 27 DESS IAS Année 2003-2004 Une procédure qui calcule le PGCD de 2 entiers void pgcd(int a, int b, int *resultat) { while (a!= b) { if (a>b) a = a - b ; else b = b - a ; *resultat = a ; M. KRAJECKI 28 DESS IAS Année 2003-2004
Une procédure qui calcule le PGCD de 2 entiers int a, b, r ; printf("a = ") ; scanf("%d", &a); printf("b = "); scanf("%d", &b); pgcd(a, b, &r) ; printf("pgcd = %d\n", r); M. KRAJECKI 29 DESS IAS Année 2003-2004