1 / 62

Programmation C

Programmation C. Dominique Rossin dominique.rossin@m4x.org. Première partie. Généralités sur la syntaxe C. Historique de C. AT&T Bell Labs 1969 : Premiere Unix 1973 Unix écrit en C B.Kerninghan, D.Ritchie, The C programming Langage, Prentice Hall, 1978

daire
Download Presentation

Programmation C

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Programmation C Dominique Rossin dominique.rossin@m4x.org

  2. Première partie Généralités sur la syntaxe C

  3. Historique de C • AT&T Bell Labs 1969 : Premiere Unix • 1973 Unix écrit en C • B.Kerninghan, D.Ritchie, The C programming Langage, Prentice Hall, 1978 • C ANSI = C ISO (1990) = C« Standard » • Kerningham & Ritchie, the C programming Langage second edition, Prentice Hall, 1988 • SP Harbison, GL Stelle jr, C-A reference Manual, fourth edition, Prentice Hall 1995

  4. Caractéristiques de C • Compilé • Typé avec des types structurés • Limité à des primitives de base mais accompagné d’une librairie standard pour les copies complexes, les entrées/sorties, la gestion de la mémoire … • Interfaçage possible avec tous les langages • ATTENTION • Langage laxiste à la compilation • Débogage parfois difficile

  5. Différences entre C et Java • Java a repris une grande partie de C mais : • C est compilé et utilise un préprocesseur • Certains mots clés changent de définition • Pas d’objets en C, juste des structures • Gestion explicite de la mémoire en C • En C on demande une taille n de mémoire • En java news’occupe de cette opération • Il faut libérer la mémoire utilisée quand on utilise plus une structure de données • En Java, le ramasseur de miettes (GC)s’en occupe • En C il faut toujours déclarer avant d’utiliser

  6. Exemple très simple en Java • Fichier Bonjour.java public class Bonjour { public static void main(String args[]) { System.out.println("Bonjour "); } // fin de main } // fin de la classe • On peut avoir plusieurs fonctions main • l'exécution du programme commence par l'appel à la fonction main du programme appelé.

  7. Un exemple très simple en C • Fichier Bonjour.c (le nom importe peu) #include <stdio.h> int main(void) { printf("Bonjour\n"); return 0; } /* fin de main */ • Il ne peut y avoir qu'une seule fonction main par programme • Elle doit retourner un int (code d'erreur Unix)

  8. Mise en œuvre • En Java • Compilation : javac Bonjour.java • produit un fichier Bonjour.class (bytecode) • commande java Bonjour : • Interprétation de Bonjour.main(String args[]) • En C • prétrait., compilation, éd. de liens : gcc Bonjour.c • produit un fichier a.out (code machine exécutable) • commande ./a.out : exécution de la fonction main

  9. Deuxième exemple • Avec : • formatage des impressions • options de compilation

  10. public class PGCD { public static void main(String args[]) { int a = 257, b = 381; if (a > 0 && b > 0) { System.out.println(" PGCD("+a+","+b+")"); while (a != b) { if (a < b) b = b-a; else a = a-b; System.out.println("=PGCD("+a+","+b+")"); } System.out.println("= "+a); } } }

  11. #include <stdio.h> int main(void) { int a= 257, b = 381; if (a > 0 && b > 0) { printf(" PGCD(%3d,%"d)\n",a,b); while (a != b) { if (a < b) b = b-a; else a = a-b; printf("=PGCD(%3d,%3d)\n",a,b); } printf("=%d\n",a); } return 0; }

  12. Exemple de formatage avec printf PGCD(257,381) "PGCD(%3d,%3d)" =PGCD(257,124) =PGCD(133,124) =PGCD( 9,124) =PGCD( 9,115)

  13. Options de compilation • Prétraitement, compilation et édition de liens : gcc –Wall –g pgcd.o –lm –o pgcd • l'option –Wall demande une compilation avec des diagnostics sur la propreté du code • l'option –g demande que la table des symboles soit ajoutée à l'exécutable • l'option –lm demande de lier la librairie mathématique • l'option –o pgcd demande que le résultat (l'exécutable) soit nommé pgcdau lieu de a.out

  14. Déclaration de variables • Syntaxe, exemples: • id_type id_variable; • id_type id1,id2; • id_type id = valeur; • Les variables locales ne sont pas initialisées implicitement • Les déclarations ne peuvent être qu'en début de bloc • Des constructions comme for(int i = …)et similaires sont interdites

  15. Types élémentaires • La représentation n'est pas normalisée : • char : entiers, codés sur 8 bits • int : généralement codés sur 32 bits, • float : généralement codés sur 32 bits (IEEE) • double : généralement codés sur 64 bits En C, une affectation peut faire perdre implicitement de la précision. On a le droit d'écrire int i = 1.5;

  16. Qualificatifs short et long • short int (ou short simplement) : 16 bits • long int (ou long simplement) : 32 ou 64 • long long int : généralement 64 bits • long double : au moins 64 bits

  17. Conversion de types arithmétiques implicites • En cas de +,*,<,… sur deux types différents: • un opérant est long double => long double • un opérant est double => conversion en double • un opérant est float => conversion en float • char et short int sont convertis en int • En cas de = d'une valeur de mauvais type : conversion vers le type de la variable

  18. sizeof • pseudo-opérateur : sizeof(type) ou sizeof(expr) • donne la taille en octets : sizeof(char)=1 • nombre entier, calculé à la compilation • "retourne" une valeur de type size_t (int ou long ?) • incorrect : • printf("%d\n",sizeof(…)); //suppose int • printf("%ld\n",sizeof(…)); // suppose long • correct • printf("%ld\n",(long)sizeof(…));

  19. Représentation des types numériques sizeof selon les systèmes char, short, int,long, long long, float, double, long double

  20. Qualificatifs signed et unsigned • pour les types entiers seulement, • modifient le domaine représenté mais pas la taille de la représentation, • signed char : un octet : -128..127 • unsigned char :un octet :0..255 • char seul : signed ou unsigned ??? • int est implicitement signed • changent la sémantique des opérations et affectations

  21. Valeurs booléennes • En C, il n'y a pas de type spécifique aux booléens, • on utilise les int • false est représenté par 0 • pas de valeur particulière pour true • test indicateur : printf("%d\n",sizeof('a'=='b')==sizeof(int));

  22. Tests, attention !!!! • En C, on a le droit d'écrire : int i; … if (i = 0) … affecte 0 à i et vaut 0, ie. faux qui est très différent de : …if (i == 0) … compare 0 à i et vaut vrai ou faux selon le cas

  23. Définition de constantes • 3 moyens en C • #define • const • enum

  24. #define • exemples • #define N (1 << 4) • #define DEUX_N ((N)+(N)) • Niveau préprocesseur = perte d'information • usage très répandu • attention aux parenthèses

  25. const • Exemples : • const int N = 1 << 4; • const int DEUX_N = N+N; • fondalementalement une déclaration de variable, • symboles utilisables par le débogueur • l'affectation est en principe interdite, • avec certains compilateurs, on a un simple warning

  26. Enumérations • Pour disposer de constantes symboliques entières sans #define • Déclaration enum nom_d_enum { const1,const2,…}; • Déclaration de variables enum nom_d_enum nom_de_variable

  27. Fonctions • Déclaration obligatoire avant toute utilisation • Récursivité à la Java • void = absence d'argument ou de valeur en retour • Exemples :

  28. #include <stdio.h> #define DEBUT 0 #define FIN 10 static int carre(int); static int cube(int n) {return carre(n)*n;} static int carre(int n) {return n*n;} int main(void) { int i; for (i = DEBUT; i < FIN; i++) printf("%3d^2=%3d,%3d^3=%3d\n",i,carre(i),cube(i)); return 0; }

  29. gcc –Wall –g carre.c –o carre • ./carre 0^2= 0, 0^3= 0 … 5^2= 25, 5^3=125 6^2= 36, 6^3=216 7^2= 49, 7^3=343

  30. Les boucles et tests • Même syntaxe qu'en Java • Les boucles for, while et do…while • while (condition) {…} • do {…} while (condition) • for (i = 0; i < 10; i++) {…} • Les structures de tests • if (condition) {} else {}

  31. Tableaux statiques et chaines de caractères • Déclaration et allocation type_des_elements nom_tab[nombre]; Initialisation (+declaration et allocation) : int primes[]={2,3,5,7,11}; // int primes[6] char s[] = "abc"; /*char s[4]; s[0]='a'; s[1]='b';s[2]='c';s[3]='\0'*/ Les indices de tableau vont de 0 à N-1 mais IL N'Y A PAS DE VERIFICATION DE DEBORDEMENT

  32. Copie d'un tableau ou d'une chaine void copie_tableau(char []t1,char []t2,int n) { while (n --> 0) t1[n]=t2[n]; } void copie_chaine(char []s1,char []s2) { int i=0; do s2=s1[i] while (s1[i++]!='\0'); }

  33. Fonctions simples sur les chaines • strlen(s) : retourne la longueur de la chaine s, sans compter le nul. • Il faut mettre #include <string.h> • strcmp(s1,s2): compare deux chaines et retourne un nombre <0,=0,>0. • atoi(s),atol(s),atof(s) : conversion vers entier, long et double • Librairie stdlib.h

  34. Structures • Déclaration struct nom {type1 c1; type2 c2;…}; • Déclaration de variable : struct nom variable; • Exemple • struct evt {int jour,mois,annee; char evt[50]}; • struct evt anniv; • anniv.jour = 14; anniv.annee=1973; • strcpy(anniv.evt,"Anniversaire de Dominique");

  35. Exemple #include <stdio.h> #include <math.h> struct point {float x; float y} p10 = {0,10}; struct rect {struct point p1; struct point p2}; static double sqr(double x) { return x*x; } static double dist(struct point p1,struct point p2){ return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y)); }

  36. int main(void) { struct rect r = {{0,5},{25,20}}; return 0; }

  37. Format d'affichage printf(format, arg1, arg2,…); format = chaine de caractères : • %c : caractère • %d : entier • %f : float • %s : chaine de caractères • %u : entier non signé char msg_erreur[20][100]; void erreur(int no) { printf("erreur numero %d:%s",no,msg_erreur[no]); }

  38. Divers • Types synonymes : typedef type nom_nouveau_type; typedef struct {int re; int im;} Complexe; Complexe z;

  39. Macros avec arguments #define mauvais_carre(x) x*x #define carre(x) ((x)*(x)) #define max(a,b) ((a)<(b)?(b): (a)) max(mauvais_carre(x+1),carre(x+1)); ((x+1*x+1)<(((x+1)*(x+1)))?…

  40. Références • La référence : • Kerningham, Ritchie, The C Programming Language, second edition, Prentice Hall, 1988

  41. Programmation C Deuxième Partie

  42. Pointeurs et adresses • Mémoire = Collection de cellules numérotées consécutivement et contenant chacun un octet • Adresse = Localisation d'une variable dans la mémoire • Pointeur = variable contenant l'adresse d'une variable • Typage d'es pointeurs : T* est le type "adresse d'un objet de type T". • Objectifs: • Passage par référence pour modifier un paramètre • efficacité dans la transmission des paramètres et du résultat • référencer des objets dont la localisation est inconnue à la compilation

  43. Référencement et déréférencement &var est l'adresse de (une référence à) la variable var *ptr est la variable pointée par le pointeur ptr. int age; printf("entrez votre age : "); scanf("%d",&age); int i=2,j=5; static void echanger(int *p1,int *p2) { int t=*p1; *p1 = *p2; *p2 = t; } echanger(&i,&j); /* i==5 et j==2*/

  44. L'adresse NULL Un pointeur dont la valeur est ((void *) 0), noté par la constante symbolique NULL ne pointe vers aucune cellule mémoire DEREFERENCER NULL provoque une erreur !!!! int main(void) { int *p; printf("%p,%p\n",p,NULL); return 0; } 0xbffffc58,(nil)

  45. 100 104 108 112 116 120 124 x y z[0] z[1] z[2] z[3] ip ip = & x; /* ip pointe sur x*/ y = *ip; /* y==1*/ *ip = 0; /* x==0*/ int x = 1, y=2, z[4], *ip; *ip = *ip+10; /*x==10*/ ip = &z[2]; /*ip pointe sur z[2]*/ ip=&y; /*ip pointe sur y*/ ++*ip; /*y==2*/ (*ip)++; /*y==3*/ 1 2 0 1 100 1 2 100 1 1 100 10 2 104 10 1 100 10 1 116 10 1 104 10 3 104

  46. Tableaux et pointeurs Le nom d'un tableau t s'évalue à l'adresse de t[0] Si un pointeur p pointe sur t[0], p+i pointe par définition sur t[i] Ainsi,après int t[N], *p=t; /*p==&t[0]*/ on a : p+i == &t[i], *(p+i) == t[i], et même t+i == &t[i], *(t+i) == t[i] Mais on ne peut pas affecter à un nom de tableau

  47. Usage idiotique des pointeurs static int somme(int *t, int n) { int i,s; for(s=0,i=0; i < n; i++) s = s+t[i]; return s; } est équivalent à : static int somme(int *t, int n) { int s = 0; while (n-- > 0) s+=*t++; /* lire *(t++) */ return s; }

  48. Déréférencements et type struct ptr->champ = (*ptr).champ typedef struct {int re; int im;} Complexe; Complexe *addition(Complexe *a,Complexe *b) { b->re=a->re+b->re; b->im=a->im+b->im; return b; } /* permet addition(u,addition(v,w)) */

  49. Liste chaînées typedef struct cell { int val; struct cell *suivant; } cell,*liste; void affiche(liste l) { for (;l;l=l->suivant) printf("%d, ",l->val); }

  50. Allocation dynamique malloc void *malloc(size_t) Permet la réservation de mémoire à l'exécution pour une variable inconnue à la compilation. malloc(n) renvoie: • l'adresse de début d'un bloc de n octets • NULL si plus aucune mémoire n'est disponible Schéma typique : /*typ p[N]; dynamique*/ typ *p=(typ *) malloc(N*sizeof(typ)); if (!p) erreur(…)

More Related