web-dev-qa-db-fra.com

Fonctions en ligne vs macros de préprocesseur

En quoi une fonction en ligne diffère-t-elle d'une macro de préprocesseur?

106
Subodh

Les macros de préprocesseur ne sont que des modèles de substitution appliqués à votre code. Ils peuvent être utilisés presque n'importe où dans votre code car ils sont remplacés par leurs extensions avant le début de la compilation.

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

Pour ce qui est de l’utilisation des macros par rapport aux fonctions intégrées dans un contexte semblable à une fonction, sachez que:

  • Les macros ne sont pas sécurisées au type et peuvent être développées, qu'elles soient correctes ou non, la phase de compilation signalera les erreurs résultant de problèmes de développement de macro.
  • Les macros peuvent être utilisées dans des contextes inattendus, ce qui entraîne des problèmes
  • Les macros sont plus flexibles, en ce sens qu'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 développement, car les expressions d'entrée sont copiées où qu'elles se trouvent dans le motif.
  • Les fonctions en ligne ne sont pas toujours garanties en ligne - certains compilateurs le font uniquement dans les versions de version, ou lorsqu'ils sont spécifiquement configurés pour le faire. En outre, dans certains cas, l’inclusion peut ne pas être possible.
  • Les fonctions en ligne peuvent fournir une portée pour les variables (en particulier les variables statiques), les macros de préprocesseur ne peuvent le faire que dans des blocs de code {...}, et les variables statiques ne se comporteront pas exactement de la même manière.
119
LBushkin

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

Par exemple, si vous souhaitez comparer 2 valeurs:

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

Les effets secondaires apparaissent si vous utilisez par exemple max(a++,b++) (a ou b sera incrémenté deux fois). Au lieu de cela, utilisez (par exemple)

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

Les fonctions Inline sont développées par le compilateur, tandis que les macros sont développées par le préprocesseur, qui est une simple substitution textuelle.

  • Il n'y a pas de vérification de type lors de l'appel de macro alors que la vérification de type est effectuée lors de l'appel de la fonction.

  • Des résultats et une inefficacité indésirables peuvent se produire lors de l’expansion de macros en raison de la réévaluation des arguments et de l’ordre des opérations. Par exemple

    #define MAX(a,b) ((a)>(b) ? (a) : (b))
    int i = 5, j = MAX(i++, 0);
    

    aboutirait à

    int i = 5, j = ((i++)>(0) ? (i++) : (0));
    
  • Les arguments de la macro ne sont pas évalués avant l'expansion de la macro

    #define MUL(a, b) a*b
    int main()
    {
      // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
      printf("%d", MUL(2+3, 3+5));
     return 0;
    }
    // Output: 16`
    
  • Le mot clé return ne peut pas être utilisé dans les macros pour renvoyer des valeurs comme dans le cas de fonctions.

  • Les fonctions en ligne peuvent être surchargées

  • Les jetons transmis aux macros peuvent être concaténés à l'aide de l'opérateur ## appelé opérateur de jeton.

  • Les macros sont généralement utilisées pour la réutilisation de code lorsque les fonctions inline sont utilisées pour éliminer le temps système (temps supplémentaire) au cours de l'appel de la fonction (en évitant le passage à un sous-programme).

14
DataCruncher

La principale différence est la vérification de type. Le compilateur vérifiera si les valeurs que vous transmettez en tant que valeurs d'entrée peuvent être transmises à la fonction. Ce n'est pas vrai avec les macros de préprocesseur - elles sont développées avant toute vérification de type et cela peut causer des bogues graves et difficiles à détecter.

Ici Plusieurs autres points moins évidents sont décrits.

12
sharptooth

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

11
RichieHindle

Les macros ignorent les espaces de noms. Et cela les rend méchants.

8

les fonctions inline sont similaires aux macros (car le code de la fonction est développé au moment de l'appel lors de la compilation), les fonctions inline sont analysées par le compilateur, alors que les macros sont développées par le préprocesseur. En conséquence, il existe plusieurs différences importantes:

  • Les fonctions en ligne suivent tous les protocoles de type sécurité appliqués aux fonctions normales.
  • Les fonctions inline sont spécifiées en utilisant la même syntaxe que toute autre fonction, sauf qu'elles incluent le mot clé inline dans la déclaration de fonction.
  • Les expressions passées en tant qu'arguments aux fonctions en ligne sont évaluées une fois.
  • Dans certains cas, les expressions passées comme arguments à des macros peuvent être évaluées plusieurs fois. http://msdn.Microsoft.com/en-us/library/bf6bf4cf.aspx

  • les macros sont développées au moment de la pré-compilation, vous ne pouvez pas les utiliser pour le débogage, mais vous pouvez utiliser des fonctions inline.

- bon article : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1 =

;

3
Ahmad

Une fonction en ligne conservera la sémantique des valeurs, alors qu'une macro de préprocesseur ne fera 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 telle que "i ++", le fait de l'exécuter deux fois est assez surprenant. Une fonction en ligne n'aura pas ce problème.

2
Michael Donohue

Une fonction inline se comporte syntaxiquement comme une fonction normale, offrant une sécurité de type et une portée pour les variables locales de la fonction et un accès aux membres de classe s'il s'agit d'une méthode. De même, lorsque vous appelez des méthodes en ligne, vous devez vous conformer aux restrictions privées/protégées.

1
heeen

Du point de vue du codage, une fonction en ligne est comme une fonction. Ainsi, les différences entre une fonction en ligne et une macro sont identiques à celles entre une fonction et une macro.

Du point de vue de la compilation, une fonction en ligne est similaire à une macro. Il est injecté directement dans le code, pas appelé.

En général, vous devriez considérer les fonctions inline comme des fonctions régulières avec une optimisation mineure mélangée. Et comme la plupart des optimisations, il appartient au compilateur de décider s’il est vraiment intéressé à l’appliquer. Souvent, le compilateur ignorera volontiers les tentatives du programmeur pour intégrer une fonction, pour diverses raisons.

0
Brian

les fonctions en ligne se comporteront comme un appel de fonction s’il existe une instruction itérative ou récursive, afin d’empêcher l’exécution répétée d’instructions. C'est très utile pour sauvegarder la mémoire globale de votre programme.

0
Arashdeep singh

En GCC (je ne suis pas sûr des autres), déclarer une fonction inline est juste un indice pour le compilateur. Il appartient toujours au compilateur en fin de journée de décider si elle inclut ou non le corps de la fonction à chaque appel.

La différence entre les fonctions en ligne et les macros de préprocesseur est relativement grande. Les macros de préprocesseur ne sont que du remplacement de texte à la fin de la journée. Vous donnez beaucoup de possibilités au compilateur de vérifier le type des arguments et du type de retour. L'évaluation des arguments est très différente (si les expressions que vous passez dans les fonctions ont des effets secondaires, le débogage sera très amusant). Il existe des différences subtiles quant à l’utilisation des fonctions et des macros. Par exemple si j'avais:

#define MACRO_FUNC(X) ...

Où MACRO_FUNC définit évidemment le corps de la fonction. Des précautions particulières doivent être prises pour qu’elle fonctionne correctement dans tous les cas. Une fonction peut être utilisée. Par exemple, un MACRO_FUNC mal écrit causerait une erreur

if(MACRO_FUNC(y)) {
 ...body
}

Une fonction normale pourrait être utilisée sans problème ici.

0
Falaina