Le langage de macro dans le C et le C++ est traitée par un analyseur dédié à la "pré-traitement" de la scène; les jetons sont traduits et la sortie est ensuite introduit dans le flux d'entrée de l'analyseur de bon. #define
et #include
jetons sont pas reconnus par le C ou C++ analyseurs eux-mêmes.
Ceci est important parce que cela signifie que quand une macro est dit "étendu", il signifie littéralement qu'. Compte tenu de
#define MAX(A, B) (A > B ? A : B)
int i = 1, j = 2;
MAX(i, j);
ce que l'analyseur C++ voit est
(i > j ? i : j);
Cependant, si on utilise la macro avec quelque chose de plus complexe, de la même expansion qui se passe:
MAX(i++, ++j);
est élargi à
(i++ > ++j ? i++ : ++j);
Si l'on fait passer quelque chose qui fait un appel de la fonction:
MAX(f(), g());
cela permettra d'élargir à
(f() > g() ? f() : g());
Si le compilateur/optimiseur peut démontrer qu' f()
n'a pas d'effets secondaires, alors il va traiter cela comme
auto fret = f();
auto gret = g();
(fret > gret) ? fret : gret;
Si il ne peut pas, alors il va falloir appeler f() et g() deux fois, par exemple:
#include <iostream>
int f() { std::cout << "f()\n"; return 1; }
int g() { std::cout << "g()\n"; return 2; }
#define MAX(A, B) (A > B ? A : B)
int main() {
MAX(f(), g());
}
Démonstration en direct: http://ideone.com/3JBAmF
De même, si nous appelions un extern
de la fonction, l'optimiseur peut ne pas être en mesure d' éviter d'appeler la fonction deux fois.