Pourquoi avez-vous le lien de la bibliothèque de mathématiques en C?
Si je comprend <stdlib.h>
ou <stdio.h>
dans un programme C je n'ai pas de lien entre ces lors de la compilation, mais je dois le lien vers <math.h>
, à l'aide de -lm
avec gcc, par exemple:
gcc test.c -o test -lm
Quelle est la raison? Pourquoi dois-je établir un lien explicite entre la bibliothèque de mathématiques, mais pas les autres bibliothèques?
Vous devez vous connecter pour publier un commentaire.
Les fonctions dans
stdlib.h
etstdio.h
avoir des implémentations enlibc.so
(oulibc.a
la liaison statique), qui est lié à votre exécutable par défaut (comme si-lc
ont été spécifiée). GCC peut être instruits pour éviter ce lien automatique avec la-nostdlib
ou-nodefaultlibs
options.Les fonctions mathématiques de
math.h
avoir des implémentations enlibm.so
(oulibm.a
la liaison statique), etlibm
est pas lié par défaut. Il y a des raisons historiques pour cettelibm
/libc
split, rien de très convaincant.Fait intéressant, le C++ runtime
libstdc++
nécessitelibm
, donc si vous compilez un programme en C++ avec GCC (g++
), vous obtiendrez automatiquementlibm
liée.-lm
n'est pas en panne). Oh bien.Rappelez-vous que C est une vieille langue, et que les Unités de police constituées sont un phénomène relativement récent. J'ai d'abord vu C sur 8 bits des processeurs où il a été beaucoup de travail à faire encore entier de 32 bits de l'arithmétique. Beaucoup de ces implémentations n'ai même pas ont un calcul en virgule flottante de la bibliothèque disposition des!
Même sur la première 68000 machines (Mac, Atari ST, Amiga), la virgule flottante coprocesseurs étaient souvent cher add-ons.
De faire tout calcul en virgule flottante, vous avez besoin d'un assez importante bibliothèque. Et le calcul a été lente. Si vous aurez rarement utilisé flotteurs. Vous avez essayé de tout faire avec des nombres entiers ou entiers à l'échelle. Quand vous avez eu à inclure les mathématiques.h, vous serrant les dents. Souvent, vous devez écrire votre propre approximations et de tables de recherche pour l'éviter.
Compromis existé pendant une longue période. Parfois, il y avait en compétition de mathématiques paquets appelés "fastmath" ou telle. Quelle est la meilleure solution pour les mathématiques? Vraiment précis mais lent des trucs? Inexacts, mais vite? De grandes tables pour les fonctions trigonométriques? Il n'était pas jusqu'à ce que les coprocesseurs été garantie dans l'ordinateur que la plupart des implémentations est devenu évident. J'imagine qu'il y a un programmeur là, quelque part à droite maintenant, en travaillant sur une puce intégrée, en essayant de décider d'intégrer dans la bibliothèque de mathématiques à gérer certains problèmes mathématiques.
C'est pourquoi les mathématiques n'était pas standard. De nombreux ou peut-être la plupart des programmes n'ont pas utilisé un seul flotteur. Si les Unités de police constituées avait toujours été autour, et des flotteurs et des doubles étaient toujours cher à fonctionner sur, pas de doute, il y aurait eu un "stdmath".
libm
n'est pas lié par défaut, mais les maths ont été standard de C89 et avant cela, le K&R, a de facto normalisée, de sorte que votre "stdmath" remarque n'a aucun sens.Parce que le ridicule pratique historique que personne n'est prêt à les réparer. La consolidation de toutes les fonctions requises par C et POSIX dans un seul fichier de bibliothèque ne serait pas seulement d'éviter cette question se pose, mais aussi d'économiser une quantité importante de temps et de la mémoire lors de la liaison dynamique, puisque chaque
.so
fichier lié nécessite les opérations de système de fichiers pour localiser et de le trouver, et quelques pages de ses variables statiques, les délocalisations, etc.Une mise en œuvre où toutes les fonctions sont dans une bibliothèque et de la
-lm
,-lpthread
,-lrt
, etc. les options sont toutes non-ops (ou un lien à vide.a
fichiers) est parfaitement conforme POSIX et certainement préférable.Note: je parle POSIX parce que C lui-même ne précise rien sur la façon dont le compilateur est invoquée. Ainsi, vous pouvez simplement traiter
gcc -std=c99 -lm
que la mise en œuvre spécifique de la manière dont le compilateur doit être appelé pour un comportement conforme.strace
avec l'une des options de synchronisation de regarder combien de démarrage de temps est consacré à la liaison dynamique, ou de comparer l'exécution de./configure
sur un système où tous les utilitaires standard sont statiques liés par rapport à l'endroit où ils sont dynamiques liés. Même intégrer application de bureau, les développeurs et les intégrateurs de systèmes sont conscients des coûts de la liaison dynamique; c'est pourquoi les choses comme prelink existent. Je suis sûr que vous pouvez trouver des repères dans certains de ces papiers.-lm
pour être accepté et les applications qui utilisent les mathématiques interfaces doivent utiliser-lm
, mais il peut être un interne à l'option traitées (ou même ignorés par le compilateur de commande, pas un fichier de bibliothèque. Ou il peut simplement être un vide.a
fichier si les interfaces sont dans la principale de la libc.strace -tt
pourrez facilement vous montrer le temps passé sur la liaison dynamique. Ce n'est pas assez. Et sur Linux, l'inspection/proc/sys/smaps
va vous montrer la surcharge de la mémoire de bibliothèques supplémentaires.Parce que
time()
et quelques autres fonctions sontbuiltin
défini dans la bibliothèque C (libc
) lui-même et GCC toujours des liens vers de la libc sauf vous utilisez le-ffreestanding
option de compilation. Cependant fonctions mathématiques vivre danslibm
qui n'est pas implicitement lié par gcc.Une explication est donnée ici:
[Modifier]
Je ne suis pas sûr que je suis d'accord avec cela, cependant. Si vous avez une bibliothèque qui fournit, disons,
sqrt()
, et que vous passez devant la bibliothèque standard, un Unix éditeur de liens de prendre votre version, non?sqrt
résultats dans un programme avec un comportement indéfini.-lm
est totalement facultatif. Toutes les idéesComme ephemient dit, la bibliothèque C (libc est lié par défaut et cette bibliothèque contient les implémentations de stdlib.h, stdio.h et de plusieurs autres types de fichiers d'en-tête. Juste pour ajouter, selon "Une Introduction à la GCC" l'éditeur de liens de commande de base pour un programme "Hello World" en C est comme ci-dessous:
Notez l'option -lc dans la troisième ligne qui relie la bibliothèque C.
Il y a une discussion approfondie de la liaison à des bibliothèques externes dans Une Introduction à la GCC de la Liaison avec les bibliothèques externes. Si une bibliothèque est un membre de la norme bibliothèques (comme stdio), alors vous n'avez pas besoin de spécifier au compilateur (vraiment à l'éditeur de liens) pour les relier.
EDIT: Après lecture de certains de l'autre des réponses et des commentaires, je pense que le libc.une référence et de la libm de référence qu'elle lie les deux ont beaucoup à dire au sujet de pourquoi les deux sont séparés.
sqrt
fonction et il fonctionne sans y compris la bibliothèque via-lm
. Merci!Je pense que c'est une sorte de arbitraire. Vous devez tracer une ligne quelque part (dont les bibliothèques sont par défaut et qui ont besoin d'être précisées).
Il vous donne la possibilité de le remplacer par un autre qui a les mêmes fonctions, mais je ne pense pas, il est très courant de le faire.
EDIT: (à partir de mes propres commentaires): je pense que gcc ne ce afin d'assurer la rétrocompatibilité avec l'original cc. Ma conjecture pourquoi les cc ne c'est parce que du temps de construction -- cc a été écrit pour les machines avec beaucoup moins de puissance que nous avons maintenant. Beaucoup de programmes ont pas de mathématiques à virgule flottante et ils ont probablement pris toutes les bibliothèques qui n'est pas couramment utilisé en dehors de la valeur par défaut. Je suppose que le temps de génération de l'OS UNIX et les outils qui vont avec ont été la force motrice.
stdlib.h
,stdio.h
sont les fichiers d'en-tête. Vous les inclure pour votre commodité. Ils ne les prévisions des symboles deviennent disponibles si vous lien dans la bonne bibliothèque. Les implémentations sont dans les fichiers de la bibliothèque, c'est là où les fonctions de vraiment vivre.Y compris
math.h
n'est que la première étape vers l'obtention de l'accès à toutes les fonctions mathématiques.Aussi, vous n'avez pas de lien contre
libm
si vous ne l'utilisez pas les fonctions, même si vous faites une#include <math.h>
qui n'est qu'une étape d'information pour vous, pour le compilateur sur les symboles.stdlib.h
,stdio.h
reportez-vous à fonctions disponibles danslibc
, qui se trouve être toujours liés de sorte que l'utilisateur n'a pas à le faire lui-même.stdio fait partie de la bibliothèque standard C qui, par défaut, gcc lien contre.
La fonction mathématique implémentations sont dans un autre libm fichier qui n'est pas liée à un défaut de sorte que vous devez le préciser -lm. En passant, il n'y a aucun rapport entre ces fichiers d'en-tête et les fichiers de bibliothèque.
Je deviner que c'est une façon de faire des applications qui ne l'utilisez pas à tous d'effectuer un peu mieux. Voici ma façon de penser sur ce.
x86 Os (et j'imagine que d'autres) ont besoin de stocker FPU état de changement de contexte. Cependant, la plupart des Systèmes d'exploitation ne vous embêtez pas à sauver/restaurer cet état après l'application tente d'utiliser la FPU pour la première fois.
En plus de cela, il y a probablement un peu de code de base dans la bibliothèque de mathématiques qui va définir la FPU à une saine base de l'état lors de la bibliothèque est chargé.
Donc, si vous n'avez pas de lien dans tout code mathématique du tout, rien de ce qui va se passer, donc le système ne permet pas de sauvegarder/restaurer toutes les FPU état à tous, en faisant des changements de contexte légèrement plus efficace.
Juste une supposition bien.
EDIT: en réponse à certains commentaires, le même principe s'applique encore à la non-FPU cas (l'idée étant que c'était pour faire des applications qui ne font pas d'utilisation libm effectuer un peu mieux).
Par exemple, si il y a un soft-FPU qui est probable dans les premiers jours de C. Puis d'avoir libm distinct pourrait éviter beaucoup de grands (et lent s'il a été utilisé) code de inutilement liée dans.
De plus, si ce n'est que la liaison statique disponible, alors un raisonnement similaire s'applique qu'elle continuerait à exécutable de tailles et de compiler les temps d'arrêt.