PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Grundsatzfragen Kompilieren von C Programmchen



Katana
14.04.10, 22:37
Hallo

Ich habe mir folgendes C Programm geschrieben das aus einer Zahl die Quadratwurzel berechnen soll.


#include<stdio.h>
#include<math.h>

int main(void)
{
double zahl, erg; /*erzeugt Variablen zahl und erg*/
printf("Bitte Zahl eingeben:\n"); /*Fordert zum eingeben der Zahl auf*/
scanf("%lf",&zahl); /*Ließt Zahl ein*/
erg=sqrt(zahl); /*Berechnet quadratwurzel aus der Zahl*/
printf("Wurzel aus der eingegebenen Zahl=%lf\n",erg); /*Zeigt die Lösung an*/
return 0;
}
Beim Compillieren mit dem Befehl "gcc -o wurzel wurzel.c" trat ein Fehler auf.

Im I-net habe ich dann gelesen das ich mit dem Befehl "gcc -o wurzel wurzel.c -lm" Kompilieren muss damit auch <math.h> eingebunden wird.
Dann hat es funktioniert.

Nun frage ich mich woher die Leute das wissen?
In der Manpage habe ich kein "-lm" gefunden.
Nur so sachen wie "fgcse-lm".


Muss ich eigentlich auch bei anderen Sachen (z.B. bei anderen #include<*.h> Dateien) jedes mal den Kompilierbefehl irgendwie modifizieren und mir irgendwelche Optionen aus den Fingern saugen?

Ohne dabei zu wissen ob ich ein Fehler im Code oder im Kompilierbefehl habe.

Als ob die Verwirrung nicht Groß genug währe gibt es auch noch den "make dateiname" Befehl mit dem man auch Kompilieren kann.

Gibt es kein Befehl mit dem man jeden C code kompilieren kann?

Wie machen es die Profis?

Irgendwie blicke ich bei dem ganzen Konzept nicht durch.

naraesk
14.04.10, 23:01
Ich habe wenig C- Kenntnisse, aber bei C++ ist dies auf jeden Fall nicht der Fall.
Mit g++ ließ es sich auch ohne Probleme kompilieren. ;)

make ist nur ein Buildtool, welches das kompilieren von größeren Projekten einfacher machen soll, kompiliert wird dabei aber dennoch mit gcc/g++.

m.o.o.
14.04.10, 23:08
Hallo.


Im I-net habe ich dann gelesen das ich mit dem Befehl "gcc -o wurzel wurzel.c -lm" Kompilieren muss damit auch <math.h> eingebunden wird.
Dann hat es funktioniert.
Hieß es da wirklich, dass mit -lm math.h eingebunden wird? Das "Einbinden" von Headerdateien übernimmt eigentlich die Präprozessoranweisung #include. Damit werden dem Compiler idR eine Vielzahl von Deklarationen (=/= Definition) für Funktionen und Variablen bekannt gemacht. Durch das Bekanntmachen kannst du die Funktionen/Variablen dann in deinem Programm verwenden. Was die Funktionen machen bzw. wo deren ausführbarer Code liegt (die Definition der Funktion/Variable (hier: schon vorkompiliert)), interessiert den Compiler erstmal nicht, für ihn ist nur wichtig, wie die Signatur der Funktion ist und welchen Rückgabewert sie hat (damit die richtige Verwendung der Funktion hinsichtlich der Datentypen überprüft werden kann).
Auf die konkrete Funktionalität wird dann beim Linken verwiesen, hier musst du mit dem Schalter -l die Bibliotheken angeben, die zum Linken verwendet werden sollen (hier: die Bibliothek "m").
Um den Unterschied zwischen Kompilieren und Linken zu verdeutlichen kannst du mal nur
gcc -c wurzel.c eingeben, da sollte sich der Compiler noch nicht beschweren. Bei einem
gcc wurzel.o sollte er meckern.


Nun frage ich mich woher die Leute das wissen?
In der Manpage habe ich kein "-lm" gefunden.
Nur so sachen wie "fgcse-lm".
Das ist auch gut, dass das nicht in der Manpage des gcc steht. Der Compiler sollte ja möglichst modular sei und ein beschränktes Wissen/Können haben; er (bzw. der Linker) verweist nur auf Funktionalität, bietet sie aber nicht selbst an.
In welcher Bibliothek die jeweiligen Funktionen stecken steht normalerweise in der Manpage bzw. Dokumentation der Funktion.


Muss ich eigentlich auch bei anderen Sachen (z.B. bei anderen #include<*.h> Dateien) jedes mal den Kompilierbefehl irgendwie modifizieren und mir irgendwelche Optionen aus den Fingern saugen?
Hängt davon ab, welche Bibliotheken (bzw. welche Funktionen aus denen) du verwendest.

Tools zum automatischen Kompilieren gibt es, kenne mich da aber nicht so gut aus.

Gruß, Florian

m.o.o.
14.04.10, 23:14
Ich habe wenig C- Kenntnisse, aber bei C++ ist dies auf jeden Fall nicht der Fall.
Mit g++ ließ es sich auch ohne Probleme kompilieren. ;)

Das ist so, weil AFAIR sqrt schon in der C++-Standard-Library enthalten ist.

derguteweka
14.04.10, 23:26
Moin,


Im I-net habe ich dann gelesen das ich mit dem Befehl "gcc -o wurzel wurzel.c -lm" Kompilieren muss damit auch <math.h> eingebunden wird.
Das ist schon mal recht unsauber formuliert. in der Datei math.h stehen u.a. Prototypen fuer alle moeglichen Funktionen, die es in der Mathematiklibrary libm gibt. Ohne die math.h zu includieren, wuerde der compiler "nur" nicht wissen, was z.b. eine Funktion wie sqrt() an Argumenten erwartet oder zurueckgibt. Er wuerde ein paar Annahmen treffen, die manchmal gut gehen, manchmal auch nicht. Aber der Compiliervorgang wuerde auch ohne die math.h funktionieren.
Nach dem Compilieren kommt aber noch das Linken. Da faellt dem Linker auf, dass in deinem wurzel.c ja gar keine Funktion namens sqrt() definiert ist...Also musst du dir entweder selbst eine Funktion namens sqrt() schreiben, die die Wurzel irgendwie berechnet, oder du nimmst die Funktion, die zufaellig schon mal jemand in die libm reingebaut hat.
Dann musst du wissen, ob die libm automatisch zu deinem restlichen Schmonz dazugelinkt wird, oder nicht. Das haengt nicht von der Sprache C ab, sondern davon wie dein Linker konfiguriert ist. Die Standardlib (libc) linkt er ueblicherweise ja von selbst...


Nun frage ich mich woher die Leute das wissen?
In der Manpage habe ich kein "-lm" gefunden.
Nur so sachen wie "fgcse-lm".
Tja, naja hm, irgendwie kommt man ja dann nach ner Weile drauf :ugly:


Muss ich eigentlich auch bei anderen Sachen (z.B. bei anderen #include<*.h> Dateien) jedes mal den Kompilierbefehl irgendwie modifizieren und mir irgendwelche Optionen aus den Fingern saugen?
Kommt halt drauf an, was du vorhast. Wenn du z.b. die zlib.h includierst, weil du irgendwelche Kompressionen/Dekompressionen programmieren willst, solltest du natuerlich auch gegen die zlib (-lz) linken; wenn du mit pthreads arbeitest, analog...


Ohne dabei zu wissen ob ich ein Fehler im Code oder im Kompilierbefehl habe.
Das findest du schon anhand der Fehlermeldungen/Warnings des gcc raus.


Als ob die Verwirrung nicht Groß genug währe gibt es auch noch den "make dateiname" Befehl mit dem man auch Kompilieren kann.
Nee, make "dateiname" nicht. Eher make "target". Aber nur dann, wenn jemand ein Makefile geschrieben hat. make macht nichts anderes, als seinerseits den gcc oder andere tools aufzurufen, um Files (z.b. binaries) aus anderen Files (z.b. sourcen) nach bestimmten Regeln (in make selbst eingebaut und anhand des Makefiles) zu erstellen.

EDIT: Hab's doch noch gefunden, ich wusste doch, dass ich mal ein Makefile geschrieben hatte, was keinen Compiler aufruft...
Hier im letzten Post:
http://www.linuxforen.de/forums/showthread.php?t=135851


Gibt es kein Befehl mit dem man jeden C code kompilieren kann?
Gibts keinen Befehl, mit dem man jede Frau rumkriegt? :D


Wie machen es die Profis?
Keine Ahnung, ich kenne keinen persoenlich. Recht haeufig kommt es vor, dass man mittels eines configure scripts sich ein Makefile erzeugen kann, und das dann mit make arbeitet. Kleine C-Programme (1-2 C-Files) compilier' ich persoenlich so lange per explizitem gcc Aufruf, bis es mir zu bloed wird und ich mir ein Makefile schreibe (was aber selten passiert).


Irgendwie blicke ich bei dem ganzen Konzept nicht durch.
Kommt schon noch mit der Zeit. VHDL find' ich unter dieser Betrachtung z.b. viel gruseliger.

Gruss
WK

Eieiei, da hab' ich mir wohl zum tippen vieeel zu lange Zeit gelassen...

naraesk
14.04.10, 23:29
Nein, auch bei C++ musst du "cmath" bzw. "math.h" einbinden via #include.
Der include- Befehl ist ja auch im Quelltext oben enthalten, nur bei C scheint reicht dies ja wohl nicht.

m.o.o.
14.04.10, 23:33
Nein, auch bei C++ musst du "cmath" bzw. "math.h" einbinden via #include.
Der include- Befehl ist ja auch im Quelltext oben enthalten, nur bei C scheint dies ja nicht zu reichen.

Naja, bin mir nicht wirklich sicher, ob sqrt schon in der Standardbibliothek enthalten ist, aber ein #include <math.h> spricht nicht zwangsweise dagegen (Unterschiede Kompilieren <-> Linken).

Gruß, Florian

jeebee
15.04.10, 20:13
Für viele grössere Libraries (GTK+ z.B.) kannst du dir mit pkg-config --cflags --libs <library> die compiler- und linker-flags generieren lassen

L00NIX
15.04.10, 21:44
Naja, bin mir nicht wirklich sicher, ob sqrt schon in der Standardbibliothek enthalten ist, aber ein #include <math.h> spricht nicht zwangsweise dagegen (Unterschiede Kompilieren <-> Linken).


Richtig.

Die Headerdatei braucht der Compiler, um die Funktionen zu verstehen und der Linker sollte dann wissen, dass er diese Funktionen aus der Math-Bibliothek, zu finden unter /usr/lib/libm.so (aha: libm, deswegen also -lm sprich: linke gegen Bibliothek m) linken soll.

Dynamisch gelinkte Programmen kann man ihre gelinkten Libraries mit dem Kommando ldd entlocken:


$ ldd /bin/ls
linux-gate.so.1 => (0xb7eed000)
librt.so.1 => /lib/i686/cmov/librt.so.1 (0xb7ecd000)
libselinux.so.1 => /lib/libselinux.so.1 (0xb7eb4000)
libacl.so.1 => /lib/libacl.so.1 (0xb7eac000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7d51000)
libpthread.so.0 => /lib/i686/cmov/libpthread.so.0 (0xb7d38000)
/lib/ld-linux.so.2 (0xb7eee000)
libdl.so.2 => /lib/i686/cmov/libdl.so.2 (0xb7d34000)
libattr.so.1 => /lib/libattr.so.1 (0xb7d2f000)


Aha, ls braucht also kein math. ;)

Gruß
L00NIX

ThorstenHirsch
15.04.10, 22:01
Naja, aber wie man von math.h auf libm.so kommt, ist immer noch offen.

m.o.o.
15.04.10, 23:54
Naja, aber wie man von math.h auf libm.so kommt, ist immer noch offen.

Muss man mMn nicht kommen. Man geht nicht von einem Header zu einer Bibliothek, sondern von einer Funktion, die man verwenden will, zu Header und Library.

Gruß, Florian

L00NIX
17.04.10, 07:00
Naja, aber wie man von math.h auf libm.so kommt, ist immer noch offen.

Also ich finde ehrlich gesagt auch kein Rezept dafür.

Bei math.h ist es beim gcc (oder cc) eben traditionell libm.so oder libm.a. Ich denke, das ist eine Frage der Implementierung (in dem Fall gcc), ich bin mir nicht sicher, gegen was man z.B. im Visual Studio linkt (die Kommanozeilentools sind ja alle in der GUI verankert, die beim Compilieren als Frontend agiert). Eventuell linkt man dort gegen "math"?

Hier gibt es noch ein paar Infos zur Nomenklatur von Shared Objects (.so), also dynamisch gelinkten Bibliotheken: Program Library HOWTO - Shared Libraries (http://www.faqs.org/docs/Linux-HOWTO/Program-Library-HOWTO.html#SHARED-LIBRARIES) (englisch)

Gruß
L00NIX

Snake85
17.04.10, 09:41
@L00NIX, m.o.o. hat das "Rezept" doch schon genannt:
[...]Man geht nicht von einem Header zu einer Bibliothek, sondern von einer Funktion, die man verwenden will, zu Header und Library.

Also einfach mal man sqrt angucken:

SQRT(3) Linux Programmer's Manual

NAME
sqrt, sqrtf, sqrtl - square root function

SYNOPSIS
#include <math.h>

double sqrt(double x);
float sqrtf(float x);
long double sqrtl(long double x);

Link with -lm.

Katana
17.04.10, 21:18
Hmm

In der Manpage der Funktion zu suchen ist mir nicht eingefallen. :rolleyes:

Das ist schon mal ganz gut.

Danke. :)