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 :

Macro C, expansion d'un define


Sujet :

C

  1. #1
    Membre habitué
    Homme Profil pro
    Architecte technique
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Par défaut Macro C, expansion d'un define
    Bonjour tout le monde,

    j'essaye de trouver une solution au problème de macro C ci-dessous.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    #define    INDEX_1   1
    #define    INDEX_2   2
     
    unsigned char   LBa_MonBuffer1[4] = {1,2,3,4};
    unsigned char   LBa_MonBuffer2[4] = {4,3,2,1};
     
    unsigned char LBa_output[4] = {0};
     
    #define   MA_SUPER_MACRO( source, index, destination ) \
    { \
        memset(destination,0,sizeof(destination) ); \
        memcpy(destination,source ## index , sizeof(destination) ); \
    }\
    /** Ce qui suit est fonctionnel **/
    MA_SUPER_MACRO( LBa_MonBuffer, 1, LBa_output ); /** Resultat : LBa_output= 1,2,3 et 4 **/
    MA_SUPER_MACRO( LBa_MonBuffer, 2, LBa_output ); /** Resultat : LBa_output = 4,3,2 et 1 **/
     
    /** Ce qui suit est NON fonctionnel **/
    MA_SUPER_MACRO( LBa_MonBuffer, INDEX_1, LBa_output ); /** Resultat attendu : LBa_output= 1,2,3 et 4 **/
    Quelqu'un pourrait me dire si ce que j'essaye de faire est possible ?

    Je vous remercie tous !

    Arnaud

  2. #2
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Essaie en ajoutant un niveau d'indirection qui va forcer l'évaluation de la macro INDEX_1 avant concaténation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define MA_SUPER_MACRO_( source, index, destination ) \
            ...
     
    #define MA_SUPER_MACRO( source, index, destination ) MA_SUPER_MACRO_( source, index, destination )

    Soit dit en passant, à quoi bon memset un buffer que l'on va memcpy de toute manière ?

  3. #3
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Bonjour,

    ta macro ressemble trop à une fonction pour ne pas en faire … une fonction ! surtout que depuis les fonctions static inline les macros qui «font du code» perdent beaucoup de leur attrait.
    De plus, comme tu présentes ça j'ai l'impression que tu vas tôt ou tard essayer de passer une variable comme paramètre index à ta macro → c'est voué à l'échec car le préprocesseur est une des premières phases de la compilation et n'existe plus au runtime.

    Ça sent le problème XY. Il serait sans doute préférable de créer un tableau de buffers que tu accéderais par une variable plutôt que de t'embourber dans une macro. Je dis ça mais je ne connais pas le pourquoi de comment tu as aboutit à cette solution, ne connaissant pas non plus le problème de départ.

    Si tu tiens absolument à faire une «macro code» la solution classique est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define FOO do { \
                  ... \
                } while(0)
    ou éventuellement d'utiliser une extension de ton compilateur, gcc propose par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define FOO ({ \
                  ...\
                })

  4. #4
    Membre habitué
    Homme Profil pro
    Architecte technique
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    ...
    Soit dit en passant, à quoi bon memset un buffer que l'on va memcpy de toute manière ?
    Bonjour et merci Matt_Houston,
    cette macro n'est qu'un exemple, quelque chose que j'ai écris pour illustrer ma question.
    Alors memset et memcpy peu importe...

  5. #5
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Pouvons-nous commencer par demander l'utilité de la question? Les macros n'ont plus leur grande utilité à par pour rendre le code moins lisible, ajouter des sources d'erreurs, et penser que le programmeur sait plus sur comment optimisé le code qu'un compilateur bien réglé...

  6. #6
    Membre habitué
    Homme Profil pro
    Architecte technique
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Par défaut
    Bonjour et merci picodev,

    voici mes réponses:

    Citation Envoyé par picodev Voir le message
    [...]De plus, comme tu présentes ça j'ai l'impression que tu vas tôt ou tard essayer de passer une variable comme paramètre index à ta macro[...]
    Non, je ne chercherai pas à passer une variable en paramètre INDEX...

    Citation Envoyé par picodev Voir le message
    [...]Je dis ça mais je ne connais pas le pourquoi de comment tu as aboutit à cette solution, ne connaissant pas non plus le problème de départ.[...]
    C'est vrai que je n'ai pas exprimé mon problème à la base. Mon souci est purement d'ordre "culture générale": J'essaie de trouver une réponse à : "Est-ce que le compilateur est capable d'expandre un define avant l'expansion de MA_SUPER_MACRO ?"

    Citation Envoyé par picodev Voir le message
    [...]surtout que depuis les fonctions static inline les macros qui «font du code» perdent beaucoup de leur attrait.[...]
    Tu m’intéresses quand tu parles de fonctions static inline. Je ne connais pas, je vais chercher.

    Merci !

  7. #7
    Membre habitué
    Homme Profil pro
    Architecte technique
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Par défaut
    Bonjour,

    Citation Envoyé par fearyourself Voir le message
    [...]Les macros n'ont plus leur grande utilité à par pour rendre le code moins lisible, ajouter des sources d'erreurs[...]
    Je ne cherche pas du tout à optimiser du code. Dire que les macros rendent le code moins lisible signifie peut être que le programmeur n'a pas trouvé un bon nom à sa macro.

    Si je lis : MACRO_IS_BITn_RESET(BYTE,BITn), nous sommes tout à fait capable je pense de savoir ce qu'est censé faire la macro... non ?

    C'est sûr que dans l'exemple pris pour illustrer ma question, ce n'est pas le cas je te l'accorde.

    Citation Envoyé par fearyourself Voir le message
    [...]et penser que le programmeur sait plus sur comment optimisé le code qu'un compilateur bien réglé.[...]
    Je vais parler de ce que je connais: l'embarqué. Les compilateurs sont écris par des humains et de ce que je peux voir quelque fois dans les résultats de compilation, c'est qu'un compilateur n'est jamais parfait même réglé par le meilleur programmeur du monde. Rien ne vaut l'humain. Après tout dépend de ce que recherche le programmeur en embarqué que je suis , performance, taille de code et sécurité.

  8. #8
    Membre habitué
    Homme Profil pro
    Architecte technique
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Par défaut [RESOLU] Macro C, expansion d'un define
    Citation Envoyé par Matt_Houston Voir le message
    Essaie en ajoutant un niveau d'indirection qui va forcer l'évaluation de la macro INDEX_1 avant concaténation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define MA_SUPER_MACRO_( source, index, destination ) \
            ...
    #define MA_SUPER_MACRO( source, index, destination ) MA_SUPER_MACRO_( source, index, destination )
    Merci Matt_Houston, ça fonctionne !!!

    Rapide et concis !

    PS : surtout que tu n'a pas essayé de me dire que les macros c'est de la crotte...

  9. #9
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par Maitre_Kanter Voir le message
    Je vais parler de ce que je connais: l'embarqué. Les compilateurs sont écris par des humains et de ce que je peux voir quelque fois dans les résultats de compilation, c'est qu'un compilateur n'est jamais parfait même réglé par le meilleur programmeur du monde. Rien ne vaut l'humain. Après tout dépend de ce que recherche le programmeur en embarqué que je suis , performance, taille de code et sécurité.
    Tant qu'à faire on peut rester et programmer en assembleur ou binaire alors ;-)

    Je pense que ce que je suis en train de dire est qu'il y a généralement 25k choses à faire avant de commencer à penser à mettre les choses sous forme de macros. Je pense aussi que j'ai eu trop de bugs liés à des soucis de macros et que j'ai passé trop de temps à comprendre comment la cascade de macros provoquait le code généré et pourquoi cela devenait du code entièrement faux...

    Pour ce qui est du code embarqué: oui souvent on ramène à ça quand on parle contre les macros... Et oui, dans le cas embarqué, souvent les compilateurs sont moins matures que pour le cas non embarqué. Mais cela ne veut pas dire que les macros sont à être utilisés à tout bout de champs. Avant C99, il y avait quelques raisons pour utiliser des macros mais je dirai encore une fois: souvent les programmeurs tentent d'écrire du code rapide quand en fait écrire du code propre, testé, maintenable est nettement plus intéressant pour la boîte, les utilisateurs, les autres programmeurs.

    On sort du sujet mais je pense que quand on voit des sujets sur des macros, il faut rappeler que leur utilisation est à prendre avec grande grande grande précaution

  10. #10
    Membre habitué
    Homme Profil pro
    Architecte technique
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Par défaut
    Ah voila une vraie réponse et je suis tout à fait d'accord avec toi !

  11. #11
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 757
    Par défaut
    Je ne suis pas d'accord

    Les macros permettent quand même de remplacer un bout de code "obscure" par un nom explicite, sans trop de prise de tête et ceci sans aucun surcoût et surprise (un appel, le compilateur ne prend pas le inline, ...)
    Et en plus cela permet de rendre lisible son code
    Il faut juste faire attention aux variables ou aux membres utilisés dans la macro.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #define RECURSIVE_UPDATE_HEIGHT(NODE) \
    	if (NODE->right_child_index != 0xFFFF) { \
    		tmp_node01 = (base + NODE->right_child_index); \
    		 \
    		tmp_val = tmp_node01->height; \
    	} else { \
    		tmp_val = 0; \
    	} \
    	 \
    	if (NODE->left_child_index != 0xFFFF) { \
    		tmp_node01 = (base + NODE->left_child_index); \
    		 \
    		tmp_val01 = tmp_node01->height; \
    	} else { \
    		tmp_val01 = 0; \
    	} \
    	 \
    	if (tmp_val > tmp_val01) { \
    		NODE->height = (tmp_val + 1); \
    	} else { \
    		NODE->height = (tmp_val01 + 1); \
    	}
     
     
    template<typename T>
    unsigned short AVL_Tree<T>::recursive_lrotation(T* node, unsigned short node_index) {
    	tmp_index = node->right_child_index;
     
    	tmp_node = (base + node->right_child_index);
     
    //	Perform rotation
    	tmp_val = tmp_node->left_child_index;
     
    	tmp_node->left_child_index = node_index;
    	node->right_child_index    = tmp_val;
     
    //	Update heights
    	RECURSIVE_UPDATE_HEIGHT(node)
    	RECURSIVE_UPDATE_HEIGHT(tmp_node)
     
    //	Return new root
    	return tmp_index;
    }
     
     
    template<typename T>
    unsigned short AVL_Tree<T>::recursive_rrotation(T* node, unsigned short node_index) {
    	tmp_index = node->left_child_index;
     
    	tmp_node = (base + node->left_child_index);
     
    //	Perform rotation
    	tmp_val = tmp_node->right_child_index;
     
    	tmp_node->right_child_index = node_index;
    	node->left_child_index      = tmp_val;
     
    //	Update heights
    	RECURSIVE_UPDATE_HEIGHT(node)
    	RECURSIVE_UPDATE_HEIGHT(tmp_node)
     
    //	Return new root
    	return tmp_index;
    }

  12. #12
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Vous semblez oublier qu'il existe des dizaines de raisons d'écrire du code C sous forme de macro. Le souci de la vitesse d'exécution est d'ailleurs bien souvent, et je rejoins picodev là-dessus, la plus mauvaise de ces raisons.

    Bon courage pour écrire du C moderne un tant soit peu portable sans macro, et je ne parle même pas de généricité.


    Maitre_Kanter, je pense que ce qui a déclenché ces commentaires annexes (et ma question précédente) c'est le fait que ton exemple soit tout pourri et ressemble à un cas réel d'utilisation mal justifié.

  13. #13
    Membre habitué
    Homme Profil pro
    Architecte technique
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    [...]Maitre_Kanter, je pense que ce qui a déclenché ces commentaires annexes (et ma question précédente) c'est le fait que ton exemple soit tout pourri et ressemble à un cas réel d'utilisation mal justifié.
    Tu as raison.

    Après je pense que beaucoup de développeurs aiment nous inonder de leur savoir sans prêter attention à la question de base...

    On est comme ça nous les développeurs, on aiment se la péter !

  14. #14
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Citation Envoyé par foetus Voir le message
    Je ne suis pas d'accord

    Les macros permettent quand même de remplacer un bout de code "obscure" par un nom explicite, sans trop de prise de tête et ceci sans aucun surcoût et surprise (un appel, le compilateur ne prend pas le inline, ...)
    Et en plus cela permet de rendre lisible son code
    Il faut juste faire attention aux variables ou aux membres utilisés dans la macro.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #define RECURSIVE_UPDATE_HEIGHT(NODE) \
    	if (NODE->right_child_index != 0xFFFF) { \
    		tmp_node01 = (base + NODE->right_child_index); \
    		 \
    		tmp_val = tmp_node01->height; \
    	} else { \
    		tmp_val = 0; \
    	} \
    	 \
    	if (NODE->left_child_index != 0xFFFF) { \
    		tmp_node01 = (base + NODE->left_child_index); \
    		 \
    		tmp_val01 = tmp_node01->height; \
    	} else { \
    		tmp_val01 = 0; \
    	} \
    	 \
    	if (tmp_val > tmp_val01) { \
    		NODE->height = (tmp_val + 1); \
    	} else { \
    		NODE->height = (tmp_val01 + 1); \
    	}
     
     
    template<typename T>
    unsigned short AVL_Tree<T>::recursive_lrotation(T* node, unsigned short node_index) {
    	tmp_index = node->right_child_index;
     
    	tmp_node = (base + node->right_child_index);
     
    //	Perform rotation
    	tmp_val = tmp_node->left_child_index;
     
    	tmp_node->left_child_index = node_index;
    	node->right_child_index    = tmp_val;
     
    //	Update heights
    	RECURSIVE_UPDATE_HEIGHT(node)
    	RECURSIVE_UPDATE_HEIGHT(tmp_node)
     
    //	Return new root
    	return tmp_index;
    }
     
     
    template<typename T>
    unsigned short AVL_Tree<T>::recursive_rrotation(T* node, unsigned short node_index) {
    	tmp_index = node->left_child_index;
     
    	tmp_node = (base + node->left_child_index);
     
    //	Perform rotation
    	tmp_val = tmp_node->right_child_index;
     
    	tmp_node->right_child_index = node_index;
    	node->left_child_index      = tmp_val;
     
    //	Update heights
    	RECURSIVE_UPDATE_HEIGHT(node)
    	RECURSIVE_UPDATE_HEIGHT(tmp_node)
     
    //	Return new root
    	return tmp_index;
    }
    Là forcément je ne peux mettre qu'un pouce rouge (et je t'assure que c'est très rare) car c'est l'exemple typique de mauvaise pratique.
    Le tout premier réflexe devrait être : «j'ai du code à factoriser je fais une fonction POINT, il me faut une sacrée bonne raison pour préférer faire une macro».
    Dans ton exemple (qui est en C++ mais passons ce serait presque la même chose en C) il n'y a aucune bonne raison de ne pas faire une fonction. L'avantage de la fonction est qu'en plus d'avoir un typage, la vérification des paramètres, … tu n'as pas besoin de faire attention «aux variables ou aux membres utilisés dans la macro».
    Et vu comment tu as écrit ta macro un simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (i_want_a_bug_very_difficult_to_debug)
      RECURSIVE_UPDATE_HEIGHT(node);
    Tu vois l'erreur ? Oui un bug facile à créer … car ici la bonne pratique si on se décide malgré tout à utiliser une «macro code» est de bien l'écrire pour éviter ce genre de problème → cf mon message précédent.

    Donc non, à moins d'avoir une raison en béton armé ON NE REMPLACE PAS UN BOUT DE CODE PAR UNE MACRO, on fait une fonction static inline si on est vraiment préoccupé par la vitesse d'exécution. Si on est préoccupé par la taille on ne le fait pas non plus car on duplique du code … qui augmente la taille au final. Et dans la majorité des cas on fait tout simplement confiance à son compilateur qui est bien plus malin que nous.

    Il est clair qu'ici je ne m'insurge pas contre le préprocesseur … juste contre l'utilisation abusive, et souvent erronée, des macros remplaçant les fonctions.

  15. #15
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 757
    Par défaut
    Je trouve que tu dis beaucoup "il ne faut pas", mais jamais "c'est comme cela qu'il faut"

    Parce si on lit bien, les macros tu n'en fais jamais (même pour des constantes ????)

    Tu as raison sur le fond . Mais ce que tu oublies de dire/ voir, c'est pour simplifier une fonction/ procédure/ méthode (isoler un bout de code)

    Et dans ce cas là, si tu ne passes par des macros tu fais comment?
    • Des fonctions statiques? après on va avoir 1 petite partie avec que static inline qui trainent
    • copié/ collé
    • Avec des "coding style" compact pour réduire coûte que coûte malgré la lisibilité
    • Chercher dans la librairie standard ou ailleurs les "trucs à remplacer". Dans mon exemple, on peut appeler std::max


    Et l'autre point, c'est qu'une fonction static inline c'est mignon, mais tu dois passer les variables locales (en plus des paramètres de la macro)
    C'est pour cela que si tu veux réutiliser la macro tu dois recréer "le contexte" (*)
    Ou des variables globales

    Après pour les bugs difficiles à trouver, tu as raison.
    Mais tu fais une macro pour simplifier et donc améliorer la lisibilité (en plus de réutilisabilité).
    Prends mon exemple, ton bug saute aux yeux. Mais il faut relire son code et au premier appel, tu vois qu'il y a un bug.
    Et si ta macro est utilisé ailleurs, tu peux la tester dans un autre contexte pour décider si c'est la macro ou le contexte qui est source de problème (level 0 du livre "Je teste mon code")


    Et pour la vérification des types: là on s'en cogne
    On veut simplifier. Toutes les variables sont connues et même tester avant (le type et les valeurs spéciales comme NULL).


    * -> en C++ on peut avoir quelques membres temporaires dans sa classe utilisés par toutes les méthodes. C'est ce que je fais

  16. #16
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Citation Envoyé par foetus Voir le message
    Je trouve que tu dis beaucoup "il ne faut pas", mais jamais "c'est comme cela qu'il faut"
    Relis-moi, s'il-te-plaît, je dis «il faut utiliser des fonctions à moins d'avoir une sacrée bonne raison».

    Citation Envoyé par picodev Voir le message
    Le tout premier réflexe devrait être : «j'ai du code à factoriser je fais une fonction POINT, il me faut une sacrée bonne raison pour préférer faire une macro».
    Citation Envoyé par foetus Voir le message
    Parce si on lit bien, les macros tu n'en fais jamais (même pour des constantes ????)
    Relis-moi bien, j'ai bien pris la peine à chaque fois de parler de macros qui remplacent une fonction, pas de tout le reste.

    Je ne comprends même pas le sens de ces deux remarques après mon
    Citation Envoyé par picodev Voir le message
    ...
    Il est clair qu'ici je ne m'insurge pas contre le préprocesseur … juste contre l'utilisation abusive, et souvent erronée, des macros remplaçant les fonctions.
    il ne faut pas remplacer une fonction par une macro = il faut écrire une fonction
    je ne m'insurge pas contre le préprocesseur = il est comme il est, il faut comprendre à quoi il sert et bien s'en servir = la fącon dont tu t'en sers est une mauvaise pratique

    Je ne peux pas être plus clair. Je suis certain que même quelqu'un faisant preuve de mauvaise foi le comprendra aisément.

    Citation Envoyé par foetus Voir le message
    Tu as raison sur le fond . Mais ce que tu oublies de dire/ voire, c'est pour simplifier une fonction/ procédure/ méthode (isoler un bout de code)

    Et dans ce cas là, si tu ne passes par des macros tu fais comment?
    • Des fonctions statiques? après on va avoir 1 petite partie avec que static inline qui trainent
    • copié/ collé
    • Avec des "coding style" compact pour réduire coûte que coûte malgré la lisibilité
    • Chercher dans la librairie standard ou ailleurs les "trucs à remplacer". Dans mon exemple, on peut appeler std::max
    Relis la norme, c'est fait pour ça les static inline !
    Quelle est la différence dans un header entre avoir une macro qui traîne et une fonction static inline qui traîne ? La différence est que tu as un bout de code factorisé qui sera inséré là où il est appelé sans que le code/appel d'une fonction soit généré (sauf si on le demande explicitement). Tu as tous les avantages de la fonction C (vérification de type, vérification des paramètres, sémantique claire) sans les désavantages des macros.
    Surtout quand la macro est aussi mal écrite que celle de ton exemple.

    Mais bon, c'est quand même un peu la base de se dire que si «c'est pour simplifier une fonction/ procédure/ méthode (isoler un bout de code)» alors on écrit une fonction …

    Citation Envoyé par foetus Voir le message
    Et l'autre point, c'est qu'une fonction static inline c'est mignon, mais tu dois passer les variables locales (en plus des paramètres de la macro)
    C'est pour cela que si tu veux réutiliser la macro tu dois recréer "le contexte" (*)
    Ou des variables globales
    En quoi est-ce un problème ? une fonction reste une fonction, qu'il y a ait ou non des paramètres ou des variables locales. Le compilateur sait gérer ça bien mieux qu'un humain.
    Laisse ce genre de boulot au compilateur qui le fera bien, plutôt que de t'embêter avec une tonne de considérations à la con que tu feras mal.

    Citation Envoyé par foetus Voir le message
    Après pour les bugs difficiles à trouver, tu as raison.
    Mais tu fais une macro pour simplifier et donc améliorer la lisibilité (en plus de réutilisabilité).
    Prends mon exemple, ton bug saute aux yeux. Mais il faut relire son code.
    En quoi ta macro améliore plus la lisibilité qu'une fonction ?
    Et, non, je suis désolé, le bug ne saute pas aux yeux en lisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (i_want_a_bug_very_difficult_to_debug)
      RECURSIVE_UPDATE_HEIGHT(node);
    Mais tu aurais voulu un truc pire ? comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while (node) {
      RECURSIVE_UPDATE_HEIGHT(node++)
    }
    De toi à moi, ce ne sont pas mes bugs mais des bugs introduits par ta mauvaise pratique qu'on peut éviter en écrivant simplement des fonctions.

    Citation Envoyé par foetus Voir le message

    Et pour la vérification des types: là on s'en cogne
    On veut simplifier. Toutes les variables sont connues et même tester avant (le type et les valeurs spéciales comme NULL).


    * -> en C++ on peut avoir quelques membres temporaires dans sa classe utilisés par toutes les méthodes. C'est ce que je fais
    bah libre à toi de t'en cogner, mais fait ça en C++ pas en C. Tu ne simplifie rien, et surtout tu ne te simplifies pas la vie.
    Si ça ressemble à une fonction. si ça fait ce qu'une fonction doit faire, si on s'en sert comme une fonction alors on écrit une fonction ; on ne fait pas une macro à la con écrite en majuscule pour avertir qu'il faut faire attention à plein de trucs en plus … c'est débile.

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

Discussions similaires

  1. Probleme entre macro , global et define
    Par freuh94 dans le forum C
    Réponses: 3
    Dernier message: 03/06/2009, 15h43
  2. MACROS et defines
    Par romeo9423 dans le forum C
    Réponses: 6
    Dernier message: 11/11/2006, 11h31
  3. problème avec const char * et #define macro
    Par CodeurNé dans le forum C
    Réponses: 5
    Dernier message: 20/09/2006, 21h25
  4. [débutant][macros] préscisions sur #define
    Par Spartan03 dans le forum Débuter
    Réponses: 2
    Dernier message: 25/04/2006, 17h44
  5. Réponses: 4
    Dernier message: 05/02/2006, 16h29

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