Les fonctions mathématiques des expressions constantes sont-elles précalculées au moment de la compilation?

J’ai tendance à utiliser des fonctions mathématiques d’expressions constantes pour plus de commodité et de cohérence (c’est-à-dire log(x)/log(2) au lieu de log(x)/0.3... ). Puisque ces fonctions ne font pas réellement partie du langage lui-même, elles ne sont pas non plus définies dans math.h (seulement déclaré), les constantes seront-elles précalculées au moment de la compilation, ou seront-elles gaspillées à l’exécution?

Certains compilateurs les évalueront au moment de la compilation, mais ce comportement n’est pas garanti (et cela pourrait également causer des problèmes). Vous devrez vérifier votre compilateur et voir ce qu’il fait.

Notez que sur de nombreux systèmes, log(2) est disponible à partir de la macro M_LN2 dans .

Cela dépend du compilateur et des indicateurs d’optimisation. Comme @AndrewyT l’a souligné, GCC a la possibilité de spécifier les fonctions qui sont constantes et pures via des atsortingbuts. Dans ce cas, la réponse est positive, elle insère le résultat en ligne, comme vous pouvez facilement le vérifier:

 $ cat constant_call_opt.c #include  float foo() { return log(2); } $ gcc -c constant_call_opt.c -S $ cat constant_call_opt.s .file "constant_call_opt.c" .text .globl foo .type foo, @function foo: pushl %ebp movl %esp, %ebp subl $4, %esp movl $0x3f317218, %eax movl %eax, -4(%ebp) flds -4(%ebp) leave ret .size foo, .-foo .ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3" .section .note.GNU-stack,"",@progbits 

aucun appel de fonction là-bas, charge juste une constante ( 0x3f317218 == 0.69314718246459961 == log(2) )

Bien que je n’aie encore d’autre compilateur à essayer, je pense que vous pouvez vous attendre au même comportement de tous les compilateurs C principaux, car c’est une optimisation sortingviale.

Ça dépend. Si le compilateur peut faire le calcul exactement comme il le ferait au moment de l’exécution, et si des optimisations de temps de liaison sont effectuées, et si la bibliothèque est conservée sous une forme quelconque de forme intermédiaire, alors oui, cela pourrait être fait.

La plupart des compilateurs ne font pas tout cela.

Dans le cas de fonctions de bibliothèque, certains compilateurs peuvent implémenter ces fonctions en tant qu’insortingnsèques, ce qui signifie que le compilateur en sait suffisamment sur les fonctions pour remplacer l’appel par une constante au moment de la compilation. Cela dépendra du compilateur. En pratique, je remarque souvent que certains compilateurs sont réticents à pré-calculer des expressions à virgule flottante au moment de la compilation, même s’ils n’impliquent aucun appel de fonction.

En règle générale, normalement, ils ne pourront ni ne seront calculés au moment de la compilation, en supposant que le compilateur n’en sait simplement pas assez sur ces fonctions pour pouvoir les calculer au moment de la compilation. Peut-être ont-ils des effets secondaires importants au moment de l’exécution?

Certains compilateurs peuvent avoir des extensions non standard dépendantes du compilateur qui permettent à l’utilisateur de fournir des informations supplémentaires sur les fonctions au compilateur, afin que le compilateur puisse optimiser les appels de fonction et même déterminer si un appel donné peut être remplacé par un compilateur. pré-calcul du temps. Par exemple, le compilateur GCC prend en charge les atsortingbuts de fonction (extension spécifique à GCC) tels que const et pure . Si les arguments sont connus au moment de la compilation, un appel à function avec l’atsortingbut const peut théoriquement être remplacé par un pré-calcul à la compilation. Bien que je ne puisse pas dire si GCC peut réellement le faire.

En C ++ (bien que votre question porte le libellé C), une nouvelle fonctionnalité planifiée est un constexpr déclaration constexpr qui remplit un objective similaire et qui est supposé avoir l’effet que vous décrivez.

Ils seront généralement calculés au moment de l’exécution (voir les autres réponses pour savoir comment les intégrer), bien que je n’utiliserais pas nécessairement le mot “gaspillage” à moins qu’il y en ait beaucoup et / ou que le code ait été exécuté de nombreuses fois.

Plutôt que de simplement mettre la valeur constante, créez une variable #define ou const qui exprime la signification de la valeur ( PI , LOG_2 , etc.) et utilisez-la à la place.

Par exemple:

 #define LOG_2 0.30102999566 

Cela ne fait aucun calcul et vous pouvez spécifier la valeur à la précision que vous souhaitez ou que vous pouvez gérer en fonction de votre environnement (32 bits v 64 bits).

Cela se produit au moment de l’exécution, car le code de la fonction n’est disponible que pendant l’étape de liaison (ce qui se produit après l’étape de compilation).

Pour optimiser l’étape, utilisez une variable globale que vous avez initialisée avant de l’utiliser.