336 Stimmen

Warum müssen Sie die Mathematik-Bibliothek in C verknüpfen?

Wenn ich oder in einem C-Programm einfüge, muss ich diese beim Kompilieren nicht verknüpfen, aber ich muss verknüpfen, beispielsweise mit -lm mit GCC:

gcc test.c -o test -lm

Was ist der Grund dafür? Warum muss ich die Mathematikbibliothek explizit verknüpfen, aber nicht die anderen Bibliotheken?

0 Stimmen

8voto

Bill the Lizard Punkte 384619

Es gibt eine gründliche Diskussion über das Verlinken externer Bibliotheken in Eine Einführung in GCC - Verlinken mit externen Bibliotheken. Wenn eine Bibliothek zu den Standardbibliotheken gehört (wie stdio), müssen Sie dem Compiler (eigentlich dem Linker) nicht angeben, dass sie verlinkt werden sollen.

Nachdem ich einige der anderen Antworten und Kommentare gelesen habe, glaube ich, dass die libc.a-Referenz und die darin verlinkte libm-Referenz viel darüber aussagen, warum die beiden getrennt sind.

Beachten Sie, dass viele der Funktionen in 'libm.a' (die Mathematik-Bibliothek) in 'math.h' definiert sind, aber nicht in libc.a vorhanden sind. Einige sind es, was verwirrend sein kann, aber die Faustregel lautet wie folgt - die C-Bibliothek enthält diejenigen Funktionen, die von ANSI vorgeschrieben sind und daher nicht das -lm benötigen, wenn Sie nur ANSI-Funktionen verwenden. Im Gegensatz dazu enthält 'libm.a' mehr Funktionen und unterstützt zusätzliche Funktionalitäten wie den matherr-Callback und die Einhaltung mehrerer alternativer Verhaltensstandards im Falle von FP-Fehlern. Weitere Details finden Sie im Abschnitt libm.

1 Stimmen

Das beantwortet nicht die Frage, warum Sie die Match-Bibliotheken separat verknüpfen müssen. Offensichtlich müssen Sie OpenGL-Bibliotheken separat verknüpfen, aber die Mathematik-Bibliotheken sind in der Regel nützlich.

0 Stimmen

@David: Richtig, das stimmt. Für mich war es aus der Frage nicht klar ersichtlich, dass es sich um den Teil handelt, nachdem der Fragesteller gefragt hat. Ich habe gerade meine Antwort bearbeitet, als du kommentiert hast.

0 Stimmen

Ich weiß den Grund, warum ich ein Programm kompiliert habe, das die sqrt-Funktion verwendet und ohne Einbindung der Bibliothek über -lm funktioniert. Danke!

6voto

ardsrk Punkte 2387

Wie ephemient sagte, wird die C-Bibliothek libc standardmäßig verknüpft und diese Bibliothek enthält die Implementierungen von stdlib.h, stdio.h und mehreren anderen Standard-Headerdateien. Nur um hinzuzufügen, gemäß "Eine Einführung in GCC" lautet der Linker-Befehl für ein einfaches "Hello World"-Programm in C wie folgt:

ld -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o
/usr/lib/crti.o /usr/libgcc-lib/i686/3.3.1/crtbegin.o
-L/usr/lib/gcc-lib/i686/3.3.1 hello.o -lgcc -lgcc_eh -lc
-lgcc -lgcc_eh /usr/lib/gcc-lib/i686/3.3.1/crtend.o /usr/lib/crtn.o

Beachten Sie die Option -lc in der dritten Zeile, die die C-Bibliothek verknüpft.

4voto

Lou Franco Punkte 85315

Ich glaube, es ist ziemlich willkürlich. Man muss irgendwo eine Grenze ziehen (welche Bibliotheken standardmäßig sind und welche angegeben werden müssen).

Es gibt Ihnen die Möglichkeit, sie durch eine andere zu ersetzen, die die gleichen Funktionen hat, aber ich glaube nicht, dass es sehr häufig vorkommt.

Ich denke, dass GCC dies tut, um die Abwärtskompatibilität mit dem ursprünglichen cc ausführbar zu erhalten. Meine Vermutung, warum cc dies tut, ist wegen der Bauzeit - cc wurde für Maschinen mit weit weniger Leistung als wir jetzt haben geschrieben. Viele Programme haben keine Gleitkomma-Mathematik, und wahrscheinlich wurde jede Bibliothek, die nicht häufig verwendet wurde, standardmäßig entfernt. Ich vermute, dass die Bauzeit des Unix-Betriebssystems und der Tools, die damit einhergehen, die treibende Kraft waren.

0 Stimmen

Ich denke, die Mentalität hinter der Frage ist, dass der Inhalt von libm weitgehend Teil der Standard-C-Bibliothek ist, warum sind sie nicht in libc?

2 Stimmen

Der Grund für gcc ist die Aufrechterhaltung der Kompatibilität mit dem Original-cc in AT&T Unix. Ich habe 1988 3B2s verwendet und musste -lm hinzufügen, um Mathematik zu erhalten. Es schien mir damals völlig willkürlich. In Visual Studio kann ich mich nicht daran erinnern, jemals Mathematik hinzufügen zu müssen, aber manchmal müssen Sie scheinbar c-runtime-Bibliotheken hinzufügen. Ich gehe davon aus, dass die Compiler-Anbieter einen Grund haben (Build-Zeit?), aber im Moment denke ich, dass gcc nur versucht, rückwärtskompatibel zu sein.

4voto

Adrian Panasiuk Punkte 7019

Wenn ich stdlib.h oder stdio.h einfüge, muss ich diese nicht verknüpfen, aber wenn ich kompiliere, muss ich verknüpfen:

stdlib.h, stdio.h sind die Header-Dateien. Sie werden zu Ihrem Komfort eingefügt. Sie prognostizieren nur, welche Symbole verfügbar werden, wenn Sie die entsprechende Bibliothek verknüpfen. Die Implementierungen befinden sich in den Bibliotheksdateien, das ist der Ort, an dem die Funktionen wirklich existieren.

Das Einbinden von math.h ist nur der erste Schritt, um Zugriff auf alle mathematischen Funktionen zu erhalten.

Sie müssen auch nicht gegen libm verknüpfen, wenn Sie dessen Funktionen nicht verwenden, selbst wenn Sie ein #include machen, was nur ein informativer Schritt für Sie und den Compiler bezüglich der Symbole ist.

stdlib.h, stdio.h verweisen auf Funktionen, die in libc verfügbar sind, was zufällig immer verknüpft wird, damit der Benutzer dies nicht selbst tun muss.

3voto

Evan Teran Punkte 83711

Ich würde vermuten, dass dies eine Möglichkeit ist, Anwendungen, die es überhaupt nicht nutzen, etwas effizienter zu machen. Hier ist meine Überlegung dazu.

x86-Betriebssysteme (und ich nehme an, auch andere) müssen den FPU-Zustand beim Kontextwechsel speichern. Die meisten Betriebssysteme kümmern sich jedoch nur darum, diesen Zustand zu speichern/wiederherzustellen, nachdem die Anwendung versucht hat, die FPU zum ersten Mal zu verwenden.

Zusätzlich dazu gibt es wahrscheinlich einige grundlegende Codes in der Mathematikbibliothek, die den FPU auf einen vernünftigen Ausgangszustand setzen, wenn die Bibliothek geladen wird.

Also, wenn du überhaupt keinen Mathematikcode einbindest, wird nichts davon passieren. Daher muss das Betriebssystem überhaupt keinen FPU-Zustand speichern/wiederherstellen, was die Kontextwechsel etwas effizienter macht.

Nur eine Vermutung jedoch.

Das gleiche Grundprinzip gilt auch für Nicht-FPU-Fälle (das Grundprinzip war, Anwendungen, die libm nicht verwenden, etwas effizienter zu machen).

Zum Beispiel, wenn es ein Soft-FPU gab, das wahrscheinlich in den frühen Tagen von C war. Dann könnte es viele große (und langsame, wenn es verwendet wurde) Codes verhindern, die unnötigerweise verknüpft werden.

Zusätzlich, wenn nur eine statische Verknüpfung verfügbar ist, dann gilt ein ähnliches Argument, dass es die Ausführungsgrößen und Kompilierzeiten niedrig halten würde.

0 Stimmen

Wenn Sie nicht mit libm verknüpfen, aber auf andere Weise auf das x87 FPU zugreifen (Operationen auf Floats zum Beispiel), dann muss der x86-Kernel den FPU-Zustand speichern. Ich glaube nicht, dass dies eine sehr gute Vermutung ist...

0 Stimmen

Natürlich muss der Kernel den Zustand des FPU weiterhin speichern/wiederherstellen, wenn Sie es manuell verwenden. Ich wollte damit sagen, dass, wenn Sie es nie verwenden (einschließlich der Verwendung von libm), der Kernel das nicht tun muss.

0 Stimmen

Echt, es kann sehr stark vom Kernel abhängen. Die Mathematik-Bibliothek, die der Kernel verwendet, könnte eine save_FPU_on_switch() Funktion haben, die sie einschaltet, während andere einfach erkennen, ob die FPU berührt wurde.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X