280 likes | 371 Views
Commentaires. Bla. Bli. Séparateur (selon versions). /*……………*/. // commentaire C++ et donc pas toujours pris en C!. Fichiers *.h. Un jeu de fichiers, chacun autosuffisant au point de vue du langage, vus un par un par le compilateur. #include " bla.h ". Fichiers *.c.
E N D
Commentaires Bla Bli Séparateur (selon versions) /*……………*/ // commentaire C++ et donc pas toujours pris en C!
Fichiers *.h Un jeu de fichiers, chacun autosuffisant au point de vue du langage, vus un par un par le compilateur #include "bla.h" Fichiers *.c Jeu de fichiers objets (un par compilation) Exécutable après édition de liens. Compilation C
Les commentaires à travers les âges • Carte: commentaire « carte » ou ligne • Console à imprimante: commentaire parenthésé; Pascal { } ou C /* */ • Terminaux « fenêtre » monochromes: retour au commentaire ligne; C++ // Ada --
Commentaires: pièges char * coucou= "bonbon" ; … … printf(" bla */ printf (coucou) ;/* blu") ; /* */ bla */ printf (coucou) ;/* blu bonbon Hélas cela arrive plus souvent qu’on ne le croit dans les programmes qui créent des sources C (yacc, lex)
\ • Backslashen fin de ligne Blabli \ Tototiti Blablitototiti Remplacement brutal Pas de blanc après le \ Pas de limite (théorique) printf("une très longue ligne\ qu’on peut continuer sans\ désemparer "); printf( " mais cette autre solution" " moins connue est quand même" "plus esthétique (indentations) " );
#definenom sans valeur définie #define LINUX … #ifdef LINUX (ici texte qui sera compilé) #endif #ifdef WINDOWS (ici texte qui sera ignoré) #endif Ou encore, utilisation très courante d’une définition pour le déboguage: #ifdef DEBUG printf("cette foutue variable vaut ici :%d\n",x) ; #endif
#define pour des inclusions uniques Premier passage: FIC_DEJA_INCLU pas défini Passages suivants: FIC_DEJA_INCLU défini Fichier FIC.h #ifndef FIC_DEJA_INCLU #define FIC_DEJA_INCLU (ici tout le code qui ne sera jamais inclus qu’une seule fois pour une compilation donnée) #endif
#define avec valeur définie, sans argument #define MAXINT 64535 est plus efficace (mais moins sûr) que constint MAXINT1 = 64535 ; (pas d’indirection par une case mémoire). X = MAXINT; strictement équivalent à X=64535 avant la compilation. X = MAXINT1; recopie d’une case mémoire dans une autre, à l’exécution.
#define avec arguments #define TOTO(X) (X*2) Ici, chaque occurrence de TOTO(texte) sera remplacée par (texte*2). Il s’agit encore d’une simple substitution textuelle, attention aux fausses impressions. Ainsi TOTO( 3) sera remplacé par (3*2) mais TOTO(2+3) sera remplacé par (2+3*2) ce qui n’est pas forcément le résultat souhaité si on s’imagine que TOTO est « comme » une fonction, qui donnerait (2+3)*2.
Plusieurs arguments #define SWAP(x, y) {inttmp=(x) ;(x)=(y) ;(y)=tmp ;} #define SWAP(tp, x, y) {tptmp=(x) ;(x)=(y) ;(y)=tmp ;} Ou avec zéro argument mais des parenthèses #define TOTO() bla
Pièges 1 #define TEST scanf("%d",var) ; printf ("%d\n",var) ; …marchera bien en général sauf si l’on écrit if (condition) TEST; l’expansion de TEST conduisant à if (condition) scanf("%d",var) ; printf ("%d\n",var) ; On écrira donc : #define TEST {scanf("%d",var) ; printf ("%d\n",var) ;}
Toujours sur-parenthèser #define TOTO(A,B) A*B #define TOTO(A,B) ((A)*(B)) #define TOTO x=3; printf("coucou \n"); #define TOTO {x=3; printf("coucou \n");} #define TOTO(x) x=3; printf("coucou \n"); #define TOTO {(x)=3; printf("coucou \n");}
Pièges 2 #define TOTO (X) (X+1) TOTO(4) devient (X) (X+1) (4) #define TOTO(X) (X+1) TOTO(4) devient (4+1)
Pièges 3 #define CODE(X) {printf("%c : %d\n",X,X) ;} …semble équivalente à la fonction qui a le même code : void code (int x) {printf("%c : %d\n",x,x) ;} Mais si on appelle en mettant la fonction f() dans X et que f() gère un compteur…
Macros préféfinies Attention aux doubles blancs soulignés (underscores), devant et derrière chaque macro : __LINE__ : donne le numéro de la ligne actuelle (remplacement par un entier) __FILE__ : donne le nom du fichier actuel (remplacement par une chaîne de caractères avec les "") __DATE__ : donne la date de la compilation (remplacement par une chaîne de caractères avec les "") sur 11 caractères ("Mar 12 2006".)3 __TIME__ : donne l'heure de la compilation (remplacement par une chaîne de caractères avec les "") sur 8 caractères "03 :23 :44". __STDC__ : 1 si le compilateur est conforme au standard ISO, 0 sinon.
Inhibition par les parenthèses (TOTO) ne sera pas substitué voidma_fonction(intx,y) ; #definema_fonction(x,y) \ {(ma_fonction)((x),(y)) ;printf("%d %d\n",(x),(y)) ;} (ma_fonction)(2,3) appelle toujours la fonction. ma_fonction(2,3) appelle la macro si elle existe, sinon la fonction. #define TOTO() définition est légal pour mieux se servir de cette possibilité
Inclusions #include <stdbla.h> Le répertoire est défini par quelque variable système #include "monbla.h" Chemin donné explicitement ou en se servant des défauts de la session.
Rappel: éviter les inclusions multiples #ifndef FIC_DEJA_INCLU #define FIC_DEJA_INCLU … #endif
Vouloir des inclusions multiples typedefenum{Pierre, Paul, Jacques} mon_type ; /* on s’embête à donner des noms significatifs aux cas */ char * mon_type_image[]= {"Pierre", "Paul", "Jacques"} ; /* mais pour le débug on est obligé de les répéter sous forme de strings sinon on n’aura que les valeurs entières*/ printf(" je suis dans le cas %s\n " ,mon_type_image(z)) ; switch (z) { case un: …
Inclusions multiples « client » #define DEF(X) X, (X suivi d’une virgule) typedefenum { #include "enum.h" } mon_type ; #undef DEF #define DEF(X) #X, char * mon_type_image[]= { #include "enum.h" #undef DEF Fichier enum.h DEF(un) DEF(deux) DEF(trois) … DEF (mille) typedefenum {un, deux, trois,…mille,} mon_type ; char * mon_type_image[]= {"un", "deux","trois",…"mille" ,} ;
Conditions #if ou ifdef ou ifndef #elif #else #endif defined (macro)
#ifdef/#ifndef/#else/#endif #ifdef DEBUG printf ("je passe par ici\n") ; #endif #ifdef LINUX … #else … #endif
#if/#elif/#else/#endif #if defined (BUFSIZE) && BUFSIZE >= 1024 … #elif defined (BUFSIZE) && BUFSIZE >= 128 … #else … #endif Ici cas d’école car defined rend 0 (faux) si la macro n’est pas définie
#error #if defined LINUX … #elifdefined WINDOWS … #else #error mais qu’est-ce que je fabrique ici ? #endif Fera une erreur et un message à l’écran indiquant une erreur de positionnement des macros ou des switchs à la compilation
stringisation # Les " sont dans l’expansion. #define MAC(X) #X … MAC(2+3*4) va être éclaté en "2+3*4" #define TOTO(X) printf("%s vaut %d\n "), #X,(X)); … TOTO(2+3) s’expanse enprintf("%s vaut %d\n "), "2+3",(2+3)); Et le code imprimera: 2+3 vaut 5 Voir utilisation dans assert
aboutement ## #define MAC(X,Y) X##Y … MAC(TOTO,TITI) va donner TOTOTITI. #define MAC(X,Y) X/**/Y (obsolete) Utile pour préfixer tous les identificateurs d’un fichier (joueurs avancés).
Déroutements de messages #LINE 44 ou #44 À partir d’ici, le compilateur « croira » que le compte de ligne repart à 44 #FILE fic.h À partie d’ici, le compilateur « croira » compiler le fichier fic.h