IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

L'instruction au préprocesseur #define


Sujet :

C

  1. #1
    Nouveau membre du Club
    Inscrit en
    Décembre 2007
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 5
    Par défaut L'instruction au préprocesseur #define
    Bonjour à tous,

    Je rencontre souvent du code qui contient des déclarations du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    #define maFonction do { \
    ... \
    } while(uneCondition);
    J'aimerais savoir en quoi est-ce plus avantageux que de déclarer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void maFonction() {
       do {
          ...
       } while(uneCondition);
    }
    Plus particulièrement,

    1. Epargne-t-on vraiement des ressources, c'est à dire, est-ce que la fonction, une fois compilée, ne va pas être identique dans les deux cas, étant donné que "..." est le même code dans les deux cas?

    2. Si oui, est-ce que le gain de vitesse ou de mémoire est-il important?

    3. Est-ce que c'est considéré comme une bonne pratique?

    En espérant qu'un guru me réponde assez vite,

    Bonne journée
    Couillotte

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pour des fonctions inline, elles sont en effet tous les avantages sur le #define, là où c'est applicable (il y a des choses que seul un #define peut faire, notamment tout ce qui implique les opérateurs # et ##).

    Le problème majeur des fonctions inline en C, c'est qu'elles ne sont "officiellement" supportées que depuis le standard C99...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    117
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mars 2006
    Messages : 117
    Par défaut
    Hello,

    je ne suis pas un fan de la pratique des macro fonctions. le principe des macros et macros fonctions c'est que code est remplacer directement dans ton block la ou se trouve l'appel de ta macro. Il n'y a donc pas d'appel de fonction (donc pas d'empilement memoire etc) donc gain de temps.

    gros defaut, il n'y a aucun controle de typage etc à l'appel de ta macro fonction vu qu'il va remplacer directement dans ton block le code de ta macro, du coup parfois les messages d'erreur sont peu clair voir absent.

    exemple plus clair :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #define MIN(x,y) ((x) > (y) ? (y) : (x))
    #define MAX(x,y) ((x) < (y) ? (y) : (x))
     
    int main(int argc, char **argv)
    {
      int l = 0;
      for (int i = 0; i < argc; i++)
      {
        for (l = 0; argv[i][l] != '\0'; l++)
          printf("min=%d, max=%d\n", MIN(i,l), MAX(i,l));
      }
      return 0;
    }
    ici on peut voir sur ce code useless, qu'il va y avoir bcp d'appel à MIN MAX.
    Si ca n'avait pas été des macro fonctions à chaque passage dans la 2eme boucle il y aurai bcp d'empilement/depilement de fonction (tu peux voir les empilements d'appel de fonction si tu le desir dans un debuggeur digne de ce nom, genre gdb):
    1. empilement: appel à printf
    2. empilement: appel à la fonction min ()
    3. depilement : retour à printf
    4. empilement : appel à max ()
    5. depilement : retour à printf
    6. depilement : retour au main


    ce qui est evidement une perte de temps machine, donc baisse de performance.

    par contre si on prend des macro fonctions comme données ci dessus, le code est traduit à la pré compilation et donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int main(int argc, char **argv)
    {
      int l = 0;
      for (int i = 0; i < argc; i++)
      {
        for (l = 0; argv[i][l] != '\0'; l++)
          printf("min=%d, max=%d\n", (i) > (l) ? (i) : (l), (i) < (l) ? (i) : (l));
      }
      return 0;
    }
    ce code n'est qu'ensuite evalué, et il possede bcp moins d'appel de fonction et sera donc plus performant.

    je me repete ce genre de programmation est à utilisé dans des cas bien precis lorsqu'on sait ce que l'on veut faire et pourquoi on le fait, sinon c'est deconseillé.

  4. #4
    Candidat au Club
    Inscrit en
    Novembre 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Novembre 2008
    Messages : 2
    Par défaut
    L'avantage est donc simplifier le code source de programme.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par khaledbenamor Voir le message
    L'avantage est donc simplifier le code source de programme.
    Non, non. Ca complexifie le code source (car ça le rend plus difficilement lisible et debuggable), mais par contre c'est supposé optimiser le code généré.
    Par contre, je ne sais pas si cette dernière assertion reste pertinente avec les compilateurs modernes, et notamment si ceux-ci ne font pas des optimisations 'inline' automatique pour du code C. Auquel cas, mieux vaut oublier ces indigestes macros.

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par khaledbenamor Voir le message
    L'avantage est donc simplifier le code source de programme.
    Citation Envoyé par 3DArchi Voir le message
    Non, non. Ca complexifie le code source (car ça le rend plus difficilement lisible et debuggable), mais par contre c'est supposé optimiser le code généré.
    Par contre, je ne sais pas si cette dernière assertion reste pertinente avec les compilateurs modernes, et notamment si ceux-ci ne font pas des optimisations 'inline' automatique pour du code C. Auquel cas, mieux vaut oublier ces indigestes macros.
    Totalement d'accord avec 3DArchi.

    J'ai eu une fois à débugger et améliorer un très gros code basé sur ce type de truc, c'est à s'arracher les cheveux , que ce soit pour retracer l'endroit où c'est défini (dans un .h ? dans lequel ? dans le source ?), pour debugger, et quand en plus ça définit des appels de certaines fonctions avec des paramètres particuliers, c'est une horreur absolue

    C'est souvent utilisé dans la bibliothèque standard, sauf que c'est pour le bien de tous (fonction simple).

    C'est à déconseiller plus que fortement dans la programmation normale...

    (à mon avis)

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par Médinoc Voir le message
    Pour des fonctions inline, elles sont en effet tous les avantages sur le #define, là où c'est applicable (il y a des choses que seul un #define peut faire, notamment tout ce qui implique les opérateurs # et ##).

    Le problème majeur des fonctions inline en C, c'est qu'elles ne sont "officiellement" supportées que depuis le standard C99...
    A l'heure actuelle, reste-t-il encore énormément de compilo qui ne respecte pas le standard C99

    Je peux comprendre que l'on ne modifie pas un (vieux) code existant pour "si peu", avec le travail que cela peut représenter...

    Mais, dans un code "actuel", et avec un compilateur datant... d'après 1999 (en gros), l'idéal n'est-il pas de préférer les fonctions inlinées quand elle se justifie (AKA: quand un profiler nous indique que nous aurions effectivement un gain à le faire)

    Pour le reste, je suis - moi aussi - tout à fait d'accord avec 3DArchi..

    Il faut toujours se rappeler qu'un code est beaucoup plus souvent lu / débuggé qu'il n'est écrit...

    Avec ce genre de definition, tu va avoir l'impression de faire quelque chose de plus efficace, car tu "aura moins de code à écrire".

    Mais au final, tu va rapidement te rendre compte que ce code de rendra le débuggage très compliqué, si:
    • ce n'est pas un code que tu as écrit toi même
    • tu as écrit ce code depuis un temps suffisemment long pour... avoir eu l'occasion d'en oublier une partie
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Comme indiqué dans la première réponse il y a quand même des choses qu'on ne peut faire qu'avec des macros. Manipuler les symboles qui sont passés à la macro par exemple.

  9. #9
    Nouveau membre du Club
    Inscrit en
    Décembre 2007
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 5
    Par défaut Merci
    Merci à tous pour toutes ces précisions ... je récapitule:

    1. On épargne en appels de fonctions, à condition que le compilateur n'optimise pas avec des "inline".

    2. C'est utile lorsque la vitesse d'execution est un critère important.

    3. Ce n'est pas forcément une bonne pratique car le code devient moins lisible (je préfère de loin une bonne vieille fonction dont on a tous l'habitude) et moins facile à débugger...

    J'oublie quelquechose?

    ++
    Couillotte

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par couillotte Voir le message
    Merci à tous pour toutes ces précisions ... je récapitule:

    1. On épargne en appels de fonctions, à condition que le compilateur n'optimise pas avec des "inline".

    2. C'est utile lorsque la vitesse d'execution est un critère important.

    3. Ce n'est pas forcément une bonne pratique car le code devient moins lisible (je préfère de loin une bonne vieille fonction dont on a tous l'habitude) et moins facile à débugger...

    J'oublie quelquechose?

    ++
    Couillotte
    Je resterais prudent sur les aspects vitesse d'exécution. Aujourd'hui, entre les optimisations du compilo, puis les gestions de cache, intuitivement je dirais que dans 90% des cas, tu ne gagnes rien!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Instruction compilateur define pour permettre "::"
    Par Mardewin dans le forum Langage
    Réponses: 3
    Dernier message: 01/06/2011, 12h28
  2. Réponses: 16
    Dernier message: 08/10/2010, 17h53
  3. [Préprocesseur] #define #if
    Par TonyEgg62 dans le forum Débuter
    Réponses: 4
    Dernier message: 19/11/2008, 01h15
  4. Directive préprocesseur #define
    Par Altrensa dans le forum C
    Réponses: 12
    Dernier message: 29/11/2007, 17h53
  5. [Crystal Report][VB6] instruction PrintReport
    Par yyyeeeaaahhh dans le forum SDK
    Réponses: 4
    Dernier message: 29/07/2002, 14h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo