• Aucun résultat trouvé

Macros en C

N/A
N/A
Protected

Academic year: 2022

Partager "Macros en C"

Copied!
15
0
0

Texte intégral

(1)

Franck Butelle

LIPN, Université Paris 13 Formation Ingénieurs SupGalilée Info 3

11/2019

(2)

Qu’est-ce qu’une macro ?

Une macro c’est un bout de code auquel on a donné un nom ! Si on utilise le nom alors il est remplacé par le bout de code.

Traité par le pré-processeur avant la compilation par recherche/substitution comme dans un éditeur de texte ! Le pré-processeur lit le code dans l’ordre des lignes Le pré-processeur ne touche pas aux chaines de car.

Deux types de macros : les "constantes" et des pseudo-fonctions

#defineTAILLE _SIZE

#define_SIZE 1024

#definef(m,n) ((m)∗_SIZE +(n))

#defineNBRES 1,\

3

int X[ ] = { NBRES }, Y[TAILLE]; /∗ TAILLE vaut 1024 ∗/

#undef_SIZE

#define_SIZE 512

int Z[TAILLE]; /∗ TAILLE vaut 512 ∗/

(3)

Une macro= un bout de code !

#defineDEBUT { printf ("Debut !\n");

#defineFIN printf ("Fin !\n"); }

#defineAFFECT(m,n) n=m

#definePRINTINT(m) printf ("%d\n",m) int main (int argc, char ∗argv[ ]) DEBUT

int i ; AFFECT(3,i);

PRINTINT(i);

FIN

Debut ! 3

Fin !

(4)

Déboguer ses macros

Affiche à l’écran le résultat de la précompilation (y compris les inclusions...)

gcc -E testMacros.c

...

#12 "testMacros.c"

int main (int argc, char ∗argv[ ]) { printf ("Debut !\n");

int i ;

i=3;printf ("%d\n",i);

printf ("Fin !\n");}

(5)

Inconvénients des macros en C

Attention aux parenthèses !

perturbe la notion de numéro de ligne pour debug en exec

Ï correction partielle par ajout par le précomp de #num_de_ligne

introduit des risques d’erreur de syntaxe :

#define f(m) != #define f (m)

peut entrainer un «excès d’interprétation» (effets de bord)

#defineX(m) (m+m) i = 3;

printf ("%d\n",X(i++));/∗ X(i++) devient i++ + i++ ∗/

(6)

Attention aux parenthèses et aux accolades

#defineSKIP_SPACES(p, limit) { \ while (p < (limit )) { \

if (∗p++ != ’ ’) { \ p−−;break; }}}

if (s != NULL)

SKIP_SPACES (s, s+lim);

else { // produit erreur de compilation car ; avant else ! // ...

}

Il faut protéger la macro soit par do{...}while(0)

soit par (...).

(7)

Avantages des macros en C

plus rapide qu’un appel de fonction Indifférent aux types :

#definemin(X, Y) ((X) < (Y) ? (X) : (Y)) doublex,d;

int y,a;

char ∗p,c;

x = min(1.1, d); −→x = ((1.1) < (d) ? (1.1) : (d));

y = min(a, 2); −→y = ((a) < (2) ? (a) : (2));

c = min(a + 28, ∗p); −→z = ((a + 28) < (∗p) ? (a + 28) : (∗p));

(8)

Stringizing : op. #

Parfois on a envie de transformer un param d’une macro en chaine de car.

#defineWARN_IF(EXP) \

do{ if (EXP) \

fprintf ( stderr , "Warning: " #EXP "\n"); \ } while (0)

/∗ ou encore ∗/

#defineWARN_IF(EXP) ({ \

if (EXP) fprintf ( stderr , "Warning " #EXP "\n"); \ })

WARN_IF (x == 0);

−→

do{ if (x == 0) fprintf ( stderr , "Warning: " "x == 0" "\n"); }while(0);

fprintf(stderr, "Warning: " "x == 0" "\n") est identique à fprintf(stderr, "Warning: x == 0\n")

(9)

Autre exemple utile

Recherche du maximum d’un tableau d’un type quelconque

B

typeof est spécifique à gcc

#definemaxTab(t, taille ) ({ \ typeof(t [0]) max = t[0]; \ for (int i=1 ; i< taille ; i++) \

max = (max > t[i]) ? max : t[ i ]; \

max; \

})

#defineSIZE 10000 doubletabd[SIZE],d;

int tabn[SIZE],n;

/∗ ... ∗/

d = maxTab(tabd,SIZE);

n = maxTab(tabn,SIZE);

(10)

Concatenation par l’opérateur ##

Eviter les répétitions struct command {

char ∗name;

void (∗function ) (void);

};

struct command commands[ ] = { { "quit", quit_command }, { "help", help_command }, // ...

};

Les deux blocs peuvent être remplacés par :

#defineCOMMAND(NAME) { #NAME, NAME ## _command } struct command commands[ ] = {

COMMAND (quit), COMMAND (help), // ...

};

(11)

Macros avec un nbre variable d’arguments

Variadic Macros

Ici on profite aussi de deux macros prédéfinies :

#definemydebug(format,...) ({ \

if (debug) \

fprintf ( stderr , "[%s, ligne %d] " format "\n", \

__FUNCTION__, __LINE__, __VA_ARGS__); \ })

mydebug("resu=%d, total=%g\n", resu, total);

Le nom de la fonction et le numéro de ligne de l’appel seront affichés : [main, ligne 18] resu=12, total=16.22

B

Il faut dans ce cas toujours au moins 2 param.

(12)

X-macros

Exemple de code normal

typedef struct { int x,y,z, t ; double radius ; } starStruct ;

void print_star (const startStruct ∗ const star ) { printf ("%s= %d\n", "x", star−>x);

printf ("%s= %d\n", "y", star−>y);

/∗ ... puis z et t ... cela peut etre long ! ∗/

printf ("%s= %g\n", "radius", star−>radius);

}

(13)

Avec X-macros

#defineMALISTE \ X(x, int) \ X(y, int) \ // etc ...

X(radius, double) typedef struct {

#define X(member, type) type member;

MALISTE

#undef X } starStruct ;

#defineFORMAT_int "%d"

#defineFORMAT_double "%g"

void print_star (const starStruct ∗const star ) {

#define X(member, type) \

printf ("%s= " FORMAT_##type "\n", #member, star−>member);

MALISTE

#undef X }

(14)

Autre exemple

enumCOLOR { red, green, blue };

char ∗color_name[] = { [red] = "red", [green] = "green", [blue] = "blue"

};

int main() {

enumCOLOR c = red;

printf ("c=%s\n", color_name[c]);

return 0;

}

(15)

avec X-macros

Pourquoi les appeler X ?

#defineCOLOR_TABLE Y(red) Y(green) Y(blue)

#defineY(a) a, enumCOLOR {

COLOR_TABLE };

#undefX

#defineY(a) #a, char ∗color_name[ ] = {

COLOR_TABLE };

#undefX int main() {

enumCOLOR c = red;

printf ("c=%s\n", color_name[c]);

}

Références

Documents relatifs

Mais d’une part, on ne l’utilisera pas dans les mêmes conditions, et d’autre part, la souplesse d’un simple fichier, plus le mécanisme d’attache des tables donnent

Je mention- nerai juste en complément que j’ai enseigné depuis 1988 à tous les niveaux : DEUG, licence, maîtrise, DEA, DESS, master, et sur quasiment tous les sujets en

Jean-Pierre ASTRUC confirme cette demande et donne pour information que les 3 partenaires de l ’ université cible veulent faire passer la convention dans leurs

De même, la phase de tests et de mise au point d’un programme reste souvent négligée par les débutants en programmation, mais les problèmes apparaissant alors peuvent

15 H 00 Questions en santé environnementale posées à la Ville de Paris par la crise de la Covid-19 : retour d’expérience et perspectives Agnès Lefranc, Cheffe du

Anne Souyris, Adjointe à la Maire de Paris en charge de la santé publique, des relations avec l’APHP, de la santé environnementale, de la lutte contre les pollutions et

Stages : 3 ème année : 4 semaines min 4 ème année : 8 semaines min 5 ème année : 18 semaines min Possibilité d’alternance en 5 ème année : contrat de

Laboratoire d’Informatique de Paris-Nord, LIPN, U PARIS 13, CNRS, M me Frédérique B ASSINO.. 3 Ce rapport est le résultat de l’évaluation du comité d’experts dont la