Qu'est-ce qu'une macro? Différence entre macro et fonction?

16

Je ne comprends pas bien le concept macro. Qu'est-ce qu'une macro? Je ne comprends pas en quoi est-ce différent de la fonction? La fonction et la macro contiennent un bloc de code. Alors, comment la macro et la fonction diffèrent-elles?

Edoardo Sorgentone
la source
15
Faites-vous référence à un langage de programmation particulier?
mkrieger1
15
Tu dois être plus précis; macro fait référence à trois concepts très différents, à peu près les macros de texte / préprocesseur de style C, les macros Lisp et les macros d'application.
chrylis -on strike-

Réponses:

7

Remarque

Je voudrais ajouter la clarification suivante après avoir observé le schéma de vote polarisant sur cette réponse.

La réponse n'a pas été écrite en gardant à l'esprit l'exactitude technique et une large généralisation. C'était une humble tentative d'expliquer dans un langage simple, la différence entre les macros et les fonctions à un débutant en programmation, sans chercher à être complet ou précis (en fait c'est loin d'être précis). Le langage de programmation C était dans mon esprit lors de la rédaction de la réponse, mais je m'excuse de ne pas l'avoir mentionné clairement et d'avoir causé une confusion (potentielle).

Je considère vraiment la réponse partagée par Jörg W Mittag . C'était perspicace de le lire (à quel point je le sais moins) et je l'ai voté peu de temps après sa publication. Je viens de commencer sur Software Engineering Stack Exchange, et l'expérience et les discussions jusqu'à présent ont été vraiment pertinentes.

Je laisserai cette réponse ici car elle peut être utile pour d'autres débutants en développement de logiciels, essayant de comprendre un concept sans s'enliser dans les précisions techniques.


La macro et la fonction représentent une unité de code autonome. Ils sont tous deux des outils qui aident à la conception modulaire d'un programme. Du point de vue du programmeur qui écrit le code source, ils semblent assez similaires. Cependant, ils diffèrent dans la façon dont ils sont traités pendant le cycle de vie d'exécution du programme.

Une macro est définie une fois et utilisée à de nombreux endroits dans un programme. La macro est développée en ligne pendant la phase de prétraitement. Ainsi, techniquement, il ne reste pas une entité distincte une fois le code source compilé. Les instructions de la définition de macro font partie des instructions du programme, tout comme les autres instructions.

Le motif derrière l'écriture d'une macro est de faciliter l'écriture et la gestion du code source pour le programmeur. Les macros sont généralement souhaitées pour des tâches plus simples où l'écriture d'une fonction à part entière serait une pénalité de surcharge / d'exécution. Voici des exemples de situations où une macro est préférable à une fonction:

  • Utiliser des valeurs constantes (telles que des valeurs mathématiques ou scientifiques) ou un paramètre spécifique au programme.

  • Impression des messages de journal ou gestion des assertions.

  • Effectuer des calculs simples ou des vérifications de conditions.

Lorsque vous utilisez une macro, il est facile de faire des changements / corrections en un seul endroit qui sont instantanément disponibles partout où la macro est utilisée dans le programme. Une simple recompilation du programme est nécessaire pour que les modifications prennent effet.

Le code de fonction, d'autre part, est compilé en tant qu'unité distincte dans le programme et est chargé dans la mémoire pendant l'exécution du programme uniquement si cela est nécessaire. Le code de fonction conserve son identité indépendante du reste du programme. Le code chargé est réutilisé si la fonction est appelée plusieurs fois. Lorsque l'appel de fonction est rencontré dans le programme en cours d'exécution, le contrôle lui est transmis par le sous-système d'exécution et le contexte du programme en cours d'exécution (adresse d'instruction de retour) est conservé.

Cependant, il y a une légère pénalité de performance qui doit être rencontrée lors de l'appel d'une fonction (changement de contexte, préservation de l'adresse de retour des instructions du programme principal, passage de paramètres et gestion des valeurs de retour, etc.). Par conséquent, l'utilisation de la fonction n'est souhaitée que pour des blocs de code complexes (contre des macros qui traitent des cas plus simples).

Avec l'expérience, un programmeur prend une décision judicieuse quant à savoir si un morceau de code sera un bon ajustement en tant que macro ou fonction dans l'architecture globale du programme.

Nimesh Neema
la source
9
Qu'en est-il de la fonction inline?
Nathan Cooper
1
Dans le langage C & co, une macro peut également être un appel de fonction. Donc, faire une distinction entre les deux n'a pas beaucoup de sens.
Sombrero Chicken
5
Et les macros de style C sont tout sauf autonomes - elles n'introduisent pas de portée lexicale et ont un accès illimité aux noms locaux dans la portée au point de substitution.
Inutile
@Sombrero Chicken: Peut-être pourriez-vous en montrer un exemple? Vous pouvez avoir des macros qui CONTIENNENT des appels de fonction, mais (AFAIK) la macro n'est pas un appel de fonction.
jamesqf
3
Il y a beaucoup de choses dans cette réponse qui sont trompeuses. Les exemples que vous citez ne sont absolument pas des situations où les macros sont «préférables» - bien au contraire en fait. Les macros ne devraient pas être utilisées pour ces choses à moins qu'il n'y ait une très bonne raison de le faire. Les performances ne sont généralement pas une bonne raison d'utiliser des macros. Pour les raisons mentionnées dans d'autres commentaires, justifier l'utilisation de macros de cette manière est susceptible d'entraîner un code sujet aux erreurs avec toutes sortes de conséquences involontaires, en particulier dans une base de code plus grande.
Ben Cottrell
65

Malheureusement, il existe plusieurs utilisations différentes du terme "macro" dans la programmation.

Dans la famille de langages Lisp, et les langages inspirés par eux, ainsi que de nombreux langages modernes fonctionnels ou inspirés des fonctionnalités comme Scala et Haskell, ainsi que certains langages impératifs comme Boo, une macro est un morceau de code qui s'exécute au moment de la compilation (ou au moins avant l'exécution pour les implémentations sans compilateur) et peut transformer l'arborescence de syntaxe abstraite (ou quel que soit l'équivalent dans le langage particulier, par exemple en Lisp, ce serait les S-Expressions) en quelque chose d'autre pendant la compilation. Par exemple, dans de nombreuses implémentations de Scheme,for est une macro qui se développe en plusieurs appels au corps. Dans les langages à typage statique, les macros sont souvent de type sécurisé, c'est-à-dire qu'elles ne peuvent pas produire de code mal typé.

Dans la famille C des langues, les macros ressemblent davantage à une substitution textuelle. Ce qui signifie également qu'ils peuvent produire du code qui n'est pas bien typé, ni même syntaxiquement légal.

Dans les macro-assembleurs, les "macros" se réfèrent aux "instructions virtuelles", c'est-à-dire aux instructions que le CPU ne prend pas en charge nativement mais qui sont utiles, et donc l'assembleur vous permet d'utiliser ces instructions et les développera en plusieurs instructions que le CPU comprend .

Dans le script d'application, une "macro" fait référence à une série d'actions que l'utilisateur peut "enregistrer" et "lire".

Tous ces éléments sont en quelque sorte des types de code exécutable, ce qui signifie qu'ils peuvent en quelque sorte être considérés comme des fonctions. Cependant, dans le cas des macros Lisp, par exemple, leurs entrées et sorties sont des fragments de programme. Dans le cas de C, leurs entrées et sorties sont des jetons. Les trois premiers ont également la distinction très importante qu'ils sont exécutés au moment de la compilation . En fait, les macros du préprocesseur C, comme son nom l'indique, sont en fait exécutées avant même que le code n'atteigne le compilateur .

Jörg W Mittag
la source
1
«Dans les langages à typage statique, les macros sont souvent sécuritaires, c'est-à-dire qu'elles ne peuvent pas produire de code qui n'est pas bien typé» - vraiment? De quelles langues parlez-vous? AFAICS, ce n'est en général possible de garantir que dans une langue typée de manière dépendante. Dans Haskell, les macros TH ne sont sécurisées que syntaxiquement, mais le vérificateur de type s'exécute ensuite. (Donc, par type, ils offrent encore moins de garanties que les modèles C ++).
partir du
1
À part les scripts d'application, je ne pense pas que les trois exemples que vous donnez soient si différents. Tous effectuent une substitution quelconque dans le programme, au lieu de sauter dans un morceau de code partagé lors de son exécution.
IMSoP
Vous pouvez peut-être étendre la mention des macros de C avec le concept général des langages de macro comme M4, car pour C, c'est essentiellement que la spécification définit un langage de macro auxiliaire CPP et standardise son utilisation avec C.
JoL
1
Le thème général semble être que les macros génèrent du code à interpréter comme faisant partie du code source d'un programme plus large, plutôt que d'être exécutées lorsque le programme est exécuté.
jpmc26
1
@ jpmc26 Je dirais que le thème général est la substitution où vous faites une petite chose et qui se transforme en grande chose. Le langage macro M4 n'est pas spécialement destiné au code. Vous pouvez l'utiliser pour générer n'importe quel texte. Il y a aussi des macros de clavier, comme cette réponse mentionnée. Vous appuyez sur 1 ou 2 touches et elles s'étendent à une plus grande quantité de touches. Les macros vim sont comme ça aussi. Enregistrez une grande séquence de commandes en mode normal sous une seule touche, et vous appelez cette séquence en exécutant la commande en mode normal qui l'exécute.
JoL
2

Dans la famille de langage C, une définition de macro , une commande de préprocesseur, spécifie un modèle de code paramétré qui est substitué à l' appel de macro sans être compilé à la définition. Cela signifie que toutes les variables libres doivent être liées dans le contexte de l'appel de macro. Les arguments de paramètre avec un effet secondaire comme i++pourraient être répétés, en utilisant plusieurs fois le paramètre. La substitution textuelle de l'argument 1 + 2de certains paramètres xse produit avant la compilation et peut provoquer un comportement inattendu x * 3( 7io9 ). Une erreur dans le corps de macro de la définition de macro apparaîtra uniquement lors de la compilation lors de l'appel de macro.

La définition de fonction spécifie du code avec des variables libres liées au contexte du corps de la fonction; pas l' appel de fonction .

La macro, cependant apparemment négative, donne accès à l'appel, au numéro de ligne et au fichier source, à l'argument sous forme de chaîne .

Joop Eggen
la source
2

En termes légèrement plus abstraits, une macro est à la syntaxe comme une fonction aux données. Une fonction (dans l'abstrait) encapsule une transformation sur les données. Il prend ses arguments en tant que données évaluées, effectue certaines opérations sur ces derniers et renvoie un résultat qui n'est également que des données.

Une macro en revanche prend une syntaxe non évaluée et opère sur cela. Pour les langages de type C, la syntaxe entre au niveau du jeton. Pour les langages avec des macros de type LISP, ils obtiennent la syntaxe représentée comme un AST. La macro doit renvoyer un nouveau morceau de syntaxe.

Ashton Wiersdorf
la source
0

Une macro fait généralement référence à quelque chose qui est développé en place , remplaçant "l'appel" de macro pendant la compilation ou le prétraitement par des instructions individuelles dans la langue cible. Au moment de l'exécution, il n'y aura généralement aucune indication sur le début et la fin de la macro.

Ceci est distinct d'un sous - programme , qui est un morceau de code réutilisable qui est situé séparément dans la mémoire, auquel le contrôle est passé lors de l'exécution . Les "fonctions", "procédures" et "méthodes" dans la plupart des langages de programmation entrent dans cette catégorie.

Comme l' explique la réponse de Jörg W Mittag , les détails exacts varient d'une langue à l'autre: dans certains, comme C, une macro effectue une substitution de texte dans le code source; dans certains, comme Lisp, il effectue la manipulation d'une forme intermédiaire comme un arbre de syntaxe abstraite. Il y a aussi des zones grises: certains langages ont une notation pour les "fonctions en ligne", qui sont définies comme une fonction, mais développées dans le programme compilé comme une macro.

La plupart des langages encouragent les programmeurs à raisonner sur chaque sous-programme de manière isolée, à définir des contrats de type pour les entrées et les sorties et à masquer d'autres informations sur le code appelant. Il y a souvent un impact sur les performances à appeler un sous-programme que les macros n'encourent pas, et les macros peuvent être capables de manipuler le programme d'une manière qu'un sous-programme ne peut pas. Les macros peuvent donc être considérées comme "de niveau inférieur" que les sous-programmes, car elles fonctionnent sur une base moins abstraite.

IMSoP
la source
0

La macro est exécutée pendant la compilation et la fonction est exécutée au moment de l'exécution.

Exemple:

#include <stdio.h>

#define macro_sum(x,y) (x+y)

int func_sum(x,y) {
    return x+y;
}

int main(void) {
    printf("%d\n", macro_sum(2,3));
    printf("%d\n", func_sum(2,3));
    return 0;
}

Ainsi, lors de la compilation, le code est réellement changé en:

#include <stdio.h>

int func_sum(x,y) {
    return x+y;
}

int main(void) {
    printf("%d\n", (2+3));
    printf("%d\n", func_sum(2,3));
    return 0;
}
david72
la source