126 votes

Fonctions en ligne et macros de préprocesseur

Quelle est la différence entre une fonction inline et une macro de préprocesseur ?

0 votes

Réponses aux questions suivantes stackoverflow.com/questions/132738/ contient des informations relatives à votre question.

0 votes

137voto

LBushkin Points 60611

Les macros de préprocesseur sont simplement des modèles de substitution appliqués à votre code. Elles peuvent être utilisées presque partout dans votre code car elles sont remplacées par leurs expansions avant que la compilation ne commence.

Les fonctions en ligne sont des fonctions réelles dont le corps est directement injecté dans leur site d'appel. Elles ne peuvent être utilisées que lorsqu'un appel de fonction est approprié.

Maintenant, en ce qui concerne l'utilisation des macros par rapport aux fonctions en ligne dans un contexte de type fonction, sachez que :

  • Les macros ne sont pas sans danger pour les types et peuvent être développées indépendamment de leur syntaxe. La phase de compilation signalera les erreurs résultant de problèmes d'expansion de macros.
  • Les macros peuvent être utilisées dans un contexte où vous ne vous y attendez pas, ce qui entraîne des problèmes
  • Les macros sont plus flexibles, dans la mesure où elles peuvent développer d'autres macros, alors que les fonctions en ligne ne le font pas nécessairement.
  • Les macros peuvent entraîner des effets secondaires en raison de leur expansion, puisque les expressions en entrée sont copiées partout où elles apparaissent dans le motif.
  • Il n'est pas toujours garanti que les fonctions inlines le soient - certains compilateurs ne le font que dans les versions de base, ou lorsqu'ils sont spécifiquement configurés pour le faire. De plus, dans certains cas, l'inlining peut ne pas être possible.
  • Les fonctions en ligne peuvent fournir une portée pour les variables (en particulier les variables statiques), les macros du préprocesseur ne peuvent le faire que dans les blocs de code {...}, et les variables statiques ne se comporteront pas exactement de la même manière.

41 votes

Il n'est pas toujours garanti que les fonctions inlines le soient : Parce que le compilateur n'inline pas si cela génère un code plus lent, etc. Le compilateur fait beaucoup d'analyse que l'ingénieur ne peut pas faire et fait la bonne chose.

14 votes

Je crois que les fonctions récursives sont un autre exemple où la plupart des compilateurs ignorent l'inlining.

0 votes

Y a-t-il des différences importantes entre le C et le C++ dans ce cas ?

80voto

ThibThib Points 3709

Premièrement, les macros du préprocesseur sont simplement "copier-coller" dans le code avant la compilation. Il n'y a donc pas de vérification du type et certains effets secondaires peut apparaître

Par exemple, si vous voulez comparer 2 valeurs :

#define max(a,b) ((a<b)?b:a)

Les effets secondaires apparaissent si vous utilisez max(a++,b++) par exemple ( a o b sera incrémenté deux fois). À la place, utilisez (par exemple)

inline int max( int a, int b) { return ((a<b)?b:a); }

5 votes

Je voudrais juste ajouter à votre exemple qu'en plus des effets secondaires, la macro peut également introduire une charge de travail supplémentaire. max(fibonacci(100), factorial(10000)) le plus grand sera calculé deux fois :(

0 votes

Tout le monde parle de la vérification de type mais vous venez de fournir un exemple concret, c'est pourquoi je vote cette réponse.

0 votes

@watashiSHUN Pourquoi le plus grand serait-il calculé deux fois ? Merci d'avance !

13voto

sharptooth Points 93379

La principale différence est la vérification des types. Le compilateur vérifie si ce que vous passez comme valeurs d'entrée est d'un type qui peut être transmis à la fonction. Ce n'est pas le cas avec les macros du préprocesseur - elles sont développées avant toute vérification de type, ce qui peut provoquer des bogues graves et difficiles à détecter.

Ici Plusieurs autres points moins évidents ont été soulignés.

12voto

RichieHindle Points 98544

Pour ajouter une autre différence à celles déjà données : vous ne pouvez pas traverser une #define dans le débogueur, mais vous pouvez avancer dans une fonction en ligne.

2voto

Michael Donohue Points 9831

Une fonction inline maintiendra la sémantique de la valeur, alors qu'une macro de préprocesseur ne fait que copier la syntaxe. Vous pouvez obtenir des bogues très subtils avec une macro de préprocesseur si vous utilisez l'argument plusieurs fois - par exemple, si l'argument contient une mutation comme "i++", avoir cette exécution deux fois est assez surprenant. Une fonction en ligne n'aura pas ce problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X