11
votes

Quand utiliser des macros en forme de fonction en C

Je lisais un certain code écrit en C ce soir et au sommet de Le fichier était le cas de la macro de forme de fonction: xxx

Cela m'a laissé me demander, pourquoi quelqu'un choisirait-il de mettre en œuvre un fonctionner de cette façon en utilisant une macro en forme de fonction au lieu de la mise en œuvre c'est comme une fonction de vanille régulière? Quels sont les avantages et Inconvénients de chaque mise en œuvre?

Merci un tas!


2 commentaires

Au fur et à mesure que les fonctions de hasch vont, c'est assez faible - mais alors, il semble que les données à traiter soient aussi simples.


En fait, il n'est pas très lumineux de faire en sorte que cela a un macro . Fonction statique en ligne est probablement plus appropriée. C a eu une inine depuis 1999 et GCC même avant cela. Cette question a été citée comme duplicate Utilisation KFIFO de Définitions . Si MS-Windows est la raison pour laquelle les personnes disent que cette macro est raisonnable, comment sont-elles liées?


6 Réponses :


3
votes

D'une part, les macros sont mauvaises parce qu'elles sont faites par le préprocesseur, ce qui ne comprend rien sur la langue et remplace Text-Remplacer. Ils ont généralement beaucoup de limitations. Je ne peux pas voir un ci-dessus, mais généralement les macros sont des solutions laides.

D'autre part, ils sont parfois encore plus rapides qu'un méthode statique en ligne . J'épaume fortement un programme court et j'ai constaté que l'appelant à une méthode statique prend environ deux fois plus de temps (juste en tête, pas le corps de fonction réel) par rapport à une macro.


4 commentaires

C'est bon à savoir. Merci! Juste curieux, quel outil utilisiez-vous pour optimiser votre code C? Je n'ai pas essayé d'optimisation auparavant et je voudrais essayer d'essayer.


Outil? Vim, GProf et la commande vénérable la commande . GPROF est un très bon profileur avec des frais généraux faibles, bien que vous devez faire attention car il ne suit pas les macros (cela ne les voit pas; une autre des réciprides de Macros).


Quelle version utilisait votre compilateur et quel niveau d'optimisation demandez-vous de votre demander?


GCC version 4.3.3 (Ubuntu 4.3.3-5ubuntu4) (g ++). L'optimisation était -O3 .



0
votes

Le C Préprocesseur peut être utilisé pour créer des fonctions en ligne. Dans votre exemple, le code semble appeler le hachage de fonction, mais il ne s'agit que d'un code en ligne.

Les avantages de faire des fonctions macro ont été éliminés lorsque C ++ introduit des fonctions en ligne. Beaucoup d'apeses plus anciennes comme MFC et ATL utilisent toujours des fonctions de macro pour faire des astuces de préprocesseur, mais cela laisse simplement le code compliqué et plus difficile à lire.


0 commentaires

1
votes

Votre exemple n'est pas vraiment une fonction du tout,

int hashThis(int fp)
{
  return ((fp)%NHASH);
}


0 commentaires

24
votes

macros comme celui-ci éviter la surcharge d'un appel de la fonction.

Cela pourrait ne pas sembler beaucoup. Mais dans votre exemple, la macro se transforme en 1-2 instructions de langue de la machine, en fonction de votre CPU:

  • Obtenez la valeur de FP hors de la mémoire et mettez-la dans un registre
  • Prenez la valeur dans le registre, effectuez un calcul de module (%) par une valeur fixe et laissez-le dans le même registre

    alors que l'équivalent de fonction serait beaucoup plus d'instructions sur la langue de la machine, généralement quelque chose comme

    • Collez la valeur de FP sur la pile
    • Appelez la fonction, qui met également la prochaine adresse (retour) sur la pile
    • peut-être construire un cadre de pile à l'intérieur de la fonction, en fonction de la convention de l'architecture de la CPU et de l'ABI
    • Obtenez la valeur de FP de la pile et mettez-la dans un registre
    • Prenez la valeur dans le registre, effectuez un calcul de module (%) par une valeur fixe et laissez-le dans le même registre
    • peut-être prendre la valeur du registre et le remettre sur la pile, en fonction de la CPU et de l'ABI
    • Si un cadre de pile a été construit, détendez-le
    • Pop L'adresse de retour de la pile et reprend des instructions d'exécution sur

      beaucoup plus de code, hein? Si vous faites quelque chose comme rendant chacun des dizaines de milliers de pixels dans une fenêtre dans une interface graphique, les choses gèrent beaucoup plus rapidement si vous utilisez la macro.

      Personnellement, je préfère utiliser C ++ en ligne comme étant plus lisible et moins sujette d'erreur, mais les inlines sont également vraiment plus un indice au compilateur qu'il n'a pas à prendre. Les macros de préprocesseur sont un marteau de luge que le compilateur ne peut pas discuter avec.


9 commentaires

WOW, vous avez raison, c'est bien plus de code pour la mettre en œuvre en tant que fonction!


C'est ce que les fonctions en ligne sont pour! :)


Liranuna: Les fonctions en ligne ne font pas partie de l'ANSI C90, ce que la plupart des compilateurs soutiennent. Ils sont seulement en C99, ou C ++


Certains compilateurs le soutiennent comme une extension, cependant.


C99 est, bien sûr, de dix ans maintenant. Tout compilateur C qui ne le supporte pas est sérieusement obsolète.


@ liw.fi: dites-le à Microsoft!


BTW ... Modulo est un enfer de beaucoup plus de 1 instruction sur chaque processeur.


@Goz: Les instructions DIV et DIVU 68000 DIVS font un quotient et un reste de 16 bits simultanés, et le 68020 s'étend sur 32 bits.


@Goz: En outre, les instructions X86 DIV et VIDIV font un quotient simultané de 8, 16 ou 32 bits et du reste (modulo). Cependant, cela me semble que comme ARM CPUS ne calcule pas le reste comme une seule opération de la machine.



3
votes

Les raisons les plus courantes (et la plus souvent erronées) Les personnes donnent pour l'utilisation de macros (dans "l'ancien clair C") sont l'argument d'efficacité. L'utilisation d'une efficacité est bonne si vous avez profilé votre code et optimise un véritable goulot d'étranglement (ou écrivez une fonction de bibliothèque qui pourrait être un goulot d'étranglement pour quelqu'un un jour). Mais la plupart des gens qui insistent sur l'utilisation de leur utilisation n'ont rien analysé et ne créent que de la confusion là où elle n'ajoute aucun avantage.

Les macros peuvent également être utilisées pour des substitutions de type de recherche et de remplacement pratiques que le langage C normal C n'est pas capable.

Certains problèmes que j'ai eu pour maintenir le code écrit par des agresseurs macro-abuseurs sont que les macros peuvent ressembler à des fonctions, mais ne figurent pas dans la table des symboles, il peut donc être très gênant d'essayer de les retracer dans leurs origines Codes (où est-ce que cette chose est définie ?!). L'écriture de macros dans toutes les capsules est évidemment utile pour les futurs lecteurs.

S'ils sont plus que des substitutions assez simples, elles peuvent également créer une certaine confusion si vous devez passer à autre chose avec un débogueur.


3 commentaires

Pourriez-vous donner un exemple d'une de ces substitutions de recherche et de remplacement qui ne peuvent être effectuées que avec des macros que vous parlez?


Lignes génératrices de code comme: #define colorval (couleur, val) int couleur ## _ Number = val; Je ne ferais pas cela moi-même trop, mais si vous avez besoin de lignes pour rouge, bleu, vert, ..., noir, alors cela peut aider.


p.212 du "Manuel de l'UNIX HATER" (p.248 dans le fichier .pdf SIMSON.net/ ref / ugh.pdf , de CS.Washington.edu /homes/weise/uhh-download.html ) discute de certaines difficultés connexes.



16
votes

Un avantage important de la mise en oeuvre macro-macro est qu'il n'est pas lié à un type de paramètre concret. Une macro en forme de fonction dans C agit, à de nombreux égards, comme une fonction de modèle en C ++ (les modèles de C ++ sont nés de macros "plus civilisés", BTW). Dans ce cas particulier, l'argument de la macro n'a pas de type concret. Cela pourrait être absolument tout ce qui est convertible en type non signé long code>. Par exemple, si l'utilisateur plaît, si l'utilisateur plaît (et s'ils sont disposés à accepter les conséquences définies par la mise en œuvre), ils peuvent transmettre des types de pointeur à cette macro.

Quoi qu'il en soit, je dois admettre que cette macro n'est pas le meilleur exemple de Flexibilité indépendante des macros, mais en général, la flexibilité est très souvent pratique. Encore une fois, lorsque certaines fonctionnalités sont implémentées par une fonction, il est limité à des types de paramètres spécifiques. Dans de nombreux cas, afin d'appliquer une opération similaire à différents types, il est nécessaire de fournir plusieurs fonctions avec différents types de paramètres (et des noms différents, car cela est c), tandis que la même chose peut être effectuée par une macro à une seule fonction. Par exemple, MACRO P>

#define ABS(x) ((x) >= 0 ? (x) : -(x))


0 commentaires