Die Funktionen in stdlib.h
und stdio.h
haben Implementierungen in libc.so
(oder libc.a
für statische Verknüpfungen), die standardmäßig mit Ihrer ausführbaren Datei verknüpft sind (als ob -lc
angegeben). GCC kann angewiesen werden, diese automatische Verknüpfung mit den Optionen -nostdlib
oder zu vermeiden -nodefaultlibs
.
Die mathematischen Funktionen in math.h
haben Implementierungen in libm.so
(oder libm.a
für statische Verknüpfungen) und libm
sind standardmäßig nicht verknüpft. Es gibt historische Gründe für diese libm
/ libc
Spaltung, von denen keiner sehr überzeugend ist.
Interessanterweise libstdc++
erfordert die C ++ - Laufzeit. libm
Wenn Sie also ein C ++ - Programm mit GCC ( g++
) kompilieren , werden Sie automatisch libm
verlinkt.
Denken Sie daran, dass C eine alte Sprache ist und dass FPUs ein relativ junges Phänomen sind. Ich habe C zum ersten Mal auf 8-Bit-Prozessoren gesehen, bei denen es eine Menge Arbeit war, sogar 32-Bit-Ganzzahlarithmetik durchzuführen. Viele dieser Implementierungen verfügten nicht einmal über eine Gleitkomma-Mathematikbibliothek!
Selbst auf den ersten 68000-Maschinen (Mac, Atari ST, Amiga) waren Gleitkomma-Coprozessoren oft teure Add-Ons.
Um all diese Gleitkomma-Berechnungen durchzuführen, brauchten Sie eine ziemlich große Bibliothek. Und die Mathematik würde langsam sein. Sie haben also selten Schwimmer benutzt. Sie haben versucht, alles mit Ganzzahlen oder skalierten Ganzzahlen zu tun. Wenn Sie math.h einbeziehen mussten, haben Sie Ihre Zähne zusammengebissen. Oft schreiben Sie Ihre eigenen Näherungswerte und Nachschlagetabellen, um dies zu vermeiden.
Kompromisse bestanden lange Zeit. Manchmal gab es konkurrierende Mathematikpakete namens "Fastmath" oder so. Was ist die beste Lösung für Mathematik? Wirklich genaues, aber langsames Zeug? Ungenau aber schnell? Große Tabellen für Triggerfunktionen? Erst als garantiert wurde, dass sich Coprozessoren im Computer befinden, wurden die meisten Implementierungen offensichtlich. Ich stelle mir vor, dass es irgendwo irgendwo einen Programmierer gibt, der an einem eingebetteten Chip arbeitet und versucht, zu entscheiden, ob er die Mathematikbibliothek einbindet, um ein mathematisches Problem zu lösen.
Deshalb war Mathe kein Standard . Viele oder vielleicht die meisten Programme verwendeten keinen einzigen Float. Wenn FPUs schon immer da gewesen wären und Floats und Doubles immer billig zu betreiben gewesen wären, hätte es zweifellos einen "Standard" gegeben.
quelle
libm
nicht standardmäßig verknüpft ist, aber Mathematik war Standard in C89, und zuvor hatte K & R es de facto standardisiert, sodass Ihre Bemerkung "stdmath" keinen Sinn ergibt.Wegen der lächerlichen historischen Praxis, die niemand reparieren will. Die Konsolidierung aller für C und POSIX erforderlichen Funktionen in einer einzigen Bibliotheksdatei würde nicht nur verhindern, dass diese Frage immer wieder gestellt wird, sondern auch beim dynamischen Verknüpfen viel Zeit und Speicherplatz sparen, da für jede
.so
verknüpfte Datei die Dateisystemoperationen erforderlich sind um es zu finden und zu finden, und ein paar Seiten für seine statischen Variablen, Verschiebungen usw.Eine Implementierung , in der alle Funktionen in einer Bibliothek sind und die
-lm
,-lpthread
,-lrt
etc. Optionen sind alle No-ops (oder einen Link zu leeren.a
Dateien) ist eines der besten POSIX konformes und sicherlich vorzuziehen.Hinweis: Ich spreche von POSIX, da C selbst nichts darüber angibt, wie der Compiler aufgerufen wird. Daher können Sie nur
gcc -std=c99 -lm
die implementierungsspezifische Methode behandeln, mit der der Compiler für konformes Verhalten aufgerufen werden muss.quelle
strace
eine der Timing-Optionen, um zu sehen, wie viel Startzeit für die dynamische Verknüpfung aufgewendet wird, oder vergleichen Sie die Ausführung./configure
auf einem System, auf dem alle Standarddienstprogramme statisch verknüpft sind, mit einem System, auf dem sie dynamisch verknüpft sind. Selbst Mainstream-Entwickler und Systemintegratoren von Desktop-Apps sind sich der Kosten einer dynamischen Verknüpfung bewusst. Aus diesem Grund gibt es Dinge wie Prelink. Ich bin sicher, dass Sie in einigen dieser Artikel Benchmarks finden können.-lm
akzeptiert und Anwendungen, die die mathematischen Schnittstellen verwenden müssen , verwenden-lm
, aber es kann eine interne Option (oder sogar ignoriert) vom Compiler Befehl behandelt werden, nicht eine tatsächliche Bibliotheksdatei. Oder es kann nur eine leere.a
Datei sein, wenn sich die Schnittstellen in der Hauptbibliothek befinden.strace -tt
zeigt Ihnen leicht die Zeit, die Sie für die dynamische Verknüpfung aufgewendet haben. Es ist nicht schön. Unter Linux zeigt die Überprüfung/proc/sys/smaps
den Speicheraufwand für zusätzliche Bibliotheken.Weil
time()
und einige andere Funktionenbuiltin
in der C-Bibliothek (libc
) selbst definiert sind und GCC immer mit libc verknüpft ist, es sei denn, Sie verwenden die-ffreestanding
Kompilierungsoption. Es leben jedoch mathematische Funktionen,libm
die nicht implizit durch gcc verknüpft sind.quelle
Eine Erklärung wird hier gegeben :
[Bearbeiten]
Ich bin mir jedoch nicht sicher, ob ich damit einverstanden bin. Wenn Sie eine Bibliothek haben, die beispielsweise bereitstellt,
sqrt()
und diese vor der Standardbibliothek übergeben, wird Ihre Version von einem Unix-Linker übernommen, oder?quelle
sqrt
ein Programm mit undefiniertem Verhalten.-lm
völlig optional ist. Irgendwelche IdeenEine ausführliche Beschreibung der Verknüpfung mit externen Bibliotheken finden Sie in Eine Einführung in GCC - Verknüpfung mit externen Bibliotheken . Wenn eine Bibliothek Mitglied der Standardbibliotheken ist (wie stdio), müssen Sie dem Compiler (wirklich dem Linker) keine Angaben machen, um sie zu verknüpfen.
EDIT: Nachdem ich einige der anderen Antworten und Kommentare gelesen habe, denke ich, dass die libc.a-Referenz und die libm-Referenz, die mit beiden verknüpft sind, viel darüber zu sagen haben, warum die beiden getrennt sind.
quelle
sqrt
Funktion verwendet und das funktioniert, ohne die Bibliothek über einzuschließen-lm
. Vielen Dank!Wie Ephemient sagte, ist die C-Bibliothek libc standardmäßig verknüpft und diese Bibliothek enthält die Implementierungen von stdlib.h, stdio.h und mehreren anderen Standard-Header-Dateien. Nur um es hinzuzufügen, laut " Eine Einführung in GCC " ist der Linker-Befehl für ein grundlegendes "Hello World" -Programm in C wie folgt:
Beachten Sie die Option -lc in der dritten Zeile, die die C-Bibliothek verbindet.
quelle
Ich denke, es ist irgendwie willkürlich. Sie müssen irgendwo eine Linie ziehen (welche Bibliotheken sind Standardbibliotheken und welche müssen angegeben werden).
Es gibt Ihnen die Möglichkeit, es durch ein anderes zu ersetzen, das die gleichen Funktionen hat, aber ich denke nicht, dass dies sehr häufig ist.
EDIT: (aus meinen eigenen Kommentaren): Ich denke, gcc tut dies, um die Abwärtskompatibilität mit dem Original-CC aufrechtzuerhalten. Meine Vermutung, warum cc dies tut, liegt an der Bauzeit - cc wurde für Maschinen geschrieben, die weitaus weniger Leistung haben als jetzt. Viele Programme haben keine Gleitkomma-Mathematik und haben wahrscheinlich jede Bibliothek, die normalerweise nicht verwendet wird, aus dem Standard genommen. Ich vermute, dass die Build-Zeit des UNIX-Betriebssystems und die damit verbundenen Tools die treibende Kraft waren.
quelle
stdlib.h
,stdio.h
Sind die Header - Dateien. Sie fügen sie für Ihre Bequemlichkeit hinzu. Sie prognostizieren nur, welche Symbole verfügbar werden, wenn Sie in der richtigen Bibliothek verlinken. Die Implementierungen befinden sich in den Bibliotheksdateien, dort leben die Funktionen wirklich.Das Einschließen
math.h
ist nur der erste Schritt, um Zugriff auf alle mathematischen Funktionen zu erhalten.Außerdem müssen Sie keine Verknüpfung herstellen,
libm
wenn Sie die Funktionen nicht verwenden, auch wenn Sie einen#include <math.h>
für Sie nur informativen Schritt für den Compiler zu den Symbolen ausführen.stdlib.h
,stdio.h
Beziehen sich auf Funktionen , die inlibc
, die so immer verbunden sein passiert , dass der Benutzer nicht es selbst nicht zu tun.quelle
stdio ist Teil der Standard-C-Bibliothek, mit der gcc standardmäßig verknüpft wird.
Die Implementierungen der mathematischen Funktionen befinden sich in einer separaten libm-Datei, mit der standardmäßig nicht verknüpft ist. Sie müssen sie daher -lm angeben. Übrigens gibt es keine Beziehung zwischen diesen Header-Dateien und Bibliotheksdateien.
quelle
Ich würde vermuten, dass es eine Möglichkeit ist, Apps, die es überhaupt nicht verwenden, etwas leistungsfähiger zu machen. Hier ist mein Denken dazu.
x86-Betriebssysteme (und ich stelle mir andere vor) müssen den FPU-Status beim Kontextwechsel speichern. Die meisten Betriebssysteme müssen diesen Status jedoch erst speichern / wiederherstellen, nachdem die App versucht hat, die FPU zum ersten Mal zu verwenden.
Darüber hinaus enthält die Mathematikbibliothek wahrscheinlich einen grundlegenden Code, der die FPU beim Laden der Bibliothek in einen normalen Basiszustand versetzt.
Wenn Sie also überhaupt keinen mathematischen Code einbinden, geschieht nichts davon. Daher muss das Betriebssystem keinen FPU-Status speichern / wiederherstellen, wodurch die Kontextwechsel etwas effizienter werden.
Nur eine Vermutung.
BEARBEITEN: Antwort auf einige der Kommentare gilt dieselbe Grundvoraussetzung immer noch für Nicht-FPU-Fälle (die Voraussetzung war, dass Apps, bei denen libm nicht verwendet wurde, eine etwas bessere Leistung erzielen).
Wenn es zum Beispiel eine Soft-FPU gibt, die in den frühen Tagen von C ähnlich war. Wenn Sie dann libm separate verwenden, kann verhindert werden, dass viel großer (und langsamer, wenn er verwendet wird) Code unnötig verknüpft wird.
Wenn nur statische Verknüpfungen verfügbar sind, gilt ein ähnliches Argument, dass die Größe der ausführbaren Dateien und die Kompilierungszeiten niedrig gehalten werden.
quelle