2016-08-20 1 views
1

Ich entwickle unter GNU/Linux Debian 8.5Fehler Verknüpfung Code mit `Boden();`, `ceil();` und `pow();`

ich ein einfaches Programm.

Wenn ich dies mit gcc prog.c kompilieren, ist es OK!

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

int main(int argc, char const *argv[]) { 

    float _f = 3.1415f; 

    floor(_f); 
    ceil(_f); 

    return 0; 
} 

Bud, wenn ich pow() hinzufügen, heißt es, dass es nicht pow finden und ich brauche gcc prog.c -lm hinzufügen, um es richtig zu machen.

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

int main(int argc, char const *argv[]) { 

    float _f = 3.1415f; 

    floor(_f); 
    ceil(_f); 
    pow(_f, 2); 

    return 0; 
} 

Wenn ich richtig, die pow(), ceil() sind floor() alle von <math.h>?

Also, warum nicht floor() und ceil() einen Kompilierungsfehler werfen, und pow() tut, ohne -lm Flagge?

+1

verwendet gefunden Keine Bezeichner mit einem Unterstrich Präfix: https://stackoverflow.com/questions/38997919/is-it-permissible- for-global-static-identifiers-to-begin-with-a-single/38998123 # 38998123 – 2501

+0

Beachten Sie, dass Sie die Rückgabewerte dieser Funktionen einer Gleitkommavariablen zuweisen müssen, damit sie verwendet werden können. Sie ändern nicht das Argument, das Sie bestehen. –

+1

@ 2501: Unterstrich gefolgt von einem Kleinbuchstaben ist in Ordnung. – Dani

Antwort

4

Technisch benötigen alle von ihnen -lm zu arbeiten. Alle ihre man Seiten enthalten diese Zeile:

Link mit -lm.

Aber dein sind keine Compiler-Fehler, sondern ein Linker-Fehler, das ist Ihr Programm kompiliert in Ordnung, aber dann, wenn die Verknüpfung, wenn Sie nicht -lm verwenden Sie es nicht in der Lage, die Umsetzung von pow() zu finden, aber es findet tatsächlich die Implementierung von ceil().

Das ist wahrscheinlich, weil in Ihrer Architektur/Konfiguration ceil() eine Inline- oder intrinsische Funktion ist, vielleicht gibt es eine einfache CPU-Anweisung, um es zu tun, so dass keine Bibliothek erforderlich ist. Aber pow() ist nicht so müssen Sie libm verknüpfen.

UPDATE: Ich habe gerade einige Versuche gemacht, und mit -O0 alle Funktionen erfordern die -lm aber mit -O2 nur pow(). Bastelei zu, dass ich die Datei /usr/include/bits/mathinline.h mit den Inline-Implementierungen von ceil() und floor() ...

+0

"* Ihr ist kein Compiler Fehler, sondern ein Linker Fehler *" - woher weißt du das? – melpomene

+1

@melpomene: Weil '-lm' eine Linkeroption ist. Hätte das OP die eigentliche exakte Nachricht "undefinierter Bezug auf" pow "enthalten, wäre es offensichtlicher gewesen, denn undefinierte Referenzen sind Linker-Zeug. – rodrigo

+0

Danke!Jetzt sehe ich! – ch3ll0v3k

3

Der Compiler nur beschwert sich über pow() und nicht floor() oder ceil() wahrscheinlich, weil es für floor() und ceil() und einen externen Anruf für pow() Inline-Code erzeugt, die nicht zur Verknüpfungszeit aufgelöst werden können, weil Sie die m Bibliothek auf der Kommandozeile vergessen: -lm steht für Link mit libm.a.

Übrigens, da Sie den Rückgabewert dieser Funktionen nicht speichern, könnte der Compiler sein intrinsisches Wissen über diese reinen Funktionen (in gewisser Weise in <math.h> übermittelt) verwenden, um die Aufrufe vollständig zu entfernen. Es könnte das für ceil() und floor() und nicht für pow() tun, die auch das beobachtete Verhalten erklären würde.

der Tat, wie kann ohne Befehlszeilenoptionen auf http://gcc.goldbolt.org/#, überprüft werden, kompiliert den Code wie:

main: 
     pushq %rbp 
     movq %rsp, %rbp 
     subq $32, %rsp 
     movl %edi, -20(%rbp) 
     movq %rsi, -32(%rbp) 
     movss .LC0(%rip), %xmm0 
     movss %xmm0, -4(%rbp) 
     cvtss2sd  -4(%rbp), %xmm0 
     movsd .LC1(%rip), %xmm1 
     call pow 
     movl $0, %eax 
     leave 
     ret 
.LC0: 
     .long 1078529622 
.LC1: 
     .long 0 
     .long 1073741824 

Aus irgendeinem Grund der Compiler für floor und ceil nur Inline-Code erzeugt, wie beobachtet.

Während mit -O2 es alles entfernt:

main: 
     xorl %eax, %eax 
     ret 

Wenn Sie den Code ändern, um die Werte in die globalen Variablen zu speichern, Bibliothek Anrufe floor(), ceil() und pow() erzeugt werden, ohne die Optimierung und die Werte werden durch die berechneten Compiler, wenn Sie mit -O2 optimieren.

+0

ich schließe , duuuh – ch3ll0v3k

+0

@ ch3ll0v3k: Sie haben nicht die '#include ' ... Ich kann nicht erraten, was Sie in Ihrer Datei haben, daher habe ich die bedingte * Wenn Sie nicht enthalten ... * – chqrlie

+0

Ich sage, wenn ich floor() verwende; es kompiliert. – ch3ll0v3k

1

Der Fehler, den Sie erhalten, ist ein Verbindungsfehler, kein Kompilierungsfehler.
Floor und ceil befinden sich möglicherweise in einer anderen Bibliothek. Im Allgemeinen ist es nicht erforderlich, dass der Compiler fehlende Header oder Bibliotheken diagnostiziert.

+1

"* Der Fehler, den Sie erhalten, ist ein Verknüpfungsfehler, kein Kompilierungsfehler *" - woher wissen Sie das? – melpomene