Pourquoi -lm n’est-il pas nécessaire dans certains cas lors de la compilation et de la liaison de code C?

J’ai un exemple de fichier ici:

#include  #include  int main(){ printf("%f\n", log(10)); } 

Quand je le comstack avec gcc sample.c -oa ça marche très bien. Je peux l’exécuter avec ./a et il produit la sortie 2.302585 comme prévu.

Pourtant, quand mon fichier ressemble à ceci:

 #include  #include  int main(){ double a = 10; printf("%f\n", log(a)); } 

il ne comstack pas avec gcc sample.c -oa . Au lieu de cela, je dois utiliser gcc sample.c -oa -lm afin que je puisse apparemment lui dire de “lier les mathématiques” … C’est là que je ne suis pas vraiment, alors pourquoi ne devrais-je pas lier les mathématiques en premier Exemple? Et qu’est-ce que cela signifie même de devoir “lier les mathématiques”? Cela fait longtemps que je n’ai pas travaillé avec les compilateurs C, alors pardonnez-moi si votre question est mauvaise.

Vérifiez le désassemblage et vous constaterez probablement que le compilateur est en train d’optimiser l’appel à log() dans le premier cas (il n’y a donc rien à lier), mais pas dans le second. Dans ce cas particulier, la glibc définit:

 # define M_LN10 2.30258509299404568402 

dans math.h , par exemple, et n’importe quelle fonction de bibliothèque standard peut être implémentée sous forme de macro, ce qui permet de calculer certaines de ces choses sans appel de fonction.

Les fonctions de la bibliothèque mathématique peuvent ne pas être appelées. Selon le document GCC , certaines fonctions en ligne sont définies et peuvent être appelées à la place dans certaines circonstances.

… La bibliothèque GNU C fournit des optimisations pour de nombreuses fonctions mathématiques fréquemment utilisées. Lorsque GNU CC est utilisé et que l’utilisateur active l’optimiseur, plusieurs nouvelles fonctions en ligne et macros sont définies. Ces nouvelles fonctions et macros ont les mêmes noms que les fonctions de la bibliothèque et sont donc utilisées à la place de ces dernières. Dans le cas de fonctions en ligne, le compilateur décidera s’il est raisonnable de les utiliser, et cette décision est généralement correcte.

Cela signifie qu’aucun appel aux fonctions de bibliothèque ne peut être nécessaire et que la vitesse du code généré peut augmenter considérablement. L’inconvénient est que la taille du code augmentera et que cette augmentation n’est pas toujours négligeable.

Pour certaines raisons, gcc optimise log (const) même avec -O0. Donc, il n’y a pas d’appel log () dans le premier cas. Vérifier l’assemblage pour vérifier:

gcc sample.c -S

Clang, par exemple, ne l’optimise pas sur O0. Mais chez O2, gcc optimise l’appel dans les deux cas.