2009-11-10 8 views
6

stworzyłem mały program, w następujący sposób:sqrt od math.h powoduje błędu łącznik „niezdefiniowana odniesienia do sqrt” tylko wtedy, gdy argument nie jest stałą

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

    int main(int argc, char *argv[]) { 
    int i; 
    double tmp; 
    double xx; 

    for(i = 1; i <= 30; i++) { 
     xx = (double) i + 0.01; 

     tmp = sqrt(xx); 
     printf("the square root of %0.4f is %0.4f\n", xx,tmp); 
     sleep(1); 
     xx = 0; 
    } 

    return 0; 
} 

Kiedy próbuję skompilować to z następujących polecenie, pojawia się błąd kompilatora.

gcc -Wall calc.c -o calc 

powraca:

/tmp/ccavWTUB.o: In function `main': 
calc.c:(.text+0x4f): undefined reference to `sqrt' 
collect2: ld returned 1 exit status 

Gdybym zastąpić zmienną w zaproszeniu do sqrt (xx) ze stałą jak sqrt (10.2), kompiluje dobrze. Lub, jeśli jawnie linkuję:

gcc -Wall -lm calc.c -o calc 

Działa również dobrze. Czy ktoś może mi powiedzieć, co to powoduje? Byłem programistą C przez długi czas (i napisałem podobne małe programy używając math.h) i nigdy nie widziałem czegoś takiego.

Moja wersja gcc następująco:

$ gcc --version 
gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3 
Copyright (C) 2008 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
$ 
+0

Czy nadal potrzebujesz '-lm', jeśli podasz' --std = c99'? –

+0

Tak. Dziwne. Próbowałem również używać -ansi do tego samego efektu. No-go without -lm – alesplin

+4

Jest to interesująca funkcja gcc, która wymaga bezpośredniego powiązania biblioteki matematycznej - przyłapuje wszystkich na pierwszym razem. To, że kompilator może po cichu zastąpić sqrt (10.2), po prostu dodaje zabawy! –

Odpowiedz

16

Jeśli spojrzeć na wyjściu kompilatora, w przypadku gdy został użyty sqrt(10.2), założę się, widać, że wezwanie do sqrt() nie jest faktycznie .

Dzieje się tak, ponieważ GCC rozpoznaje kilka funkcji, które może specjalnie traktować. Daje to możliwość dokonywania pewnych optymalizacji, w tym przypadku Constant folding. Takie specjalne funkcje są nazywane Built-ins.

W przypadku, gdy musi on być połączony z biblioteką matematyczną (ponieważ wywołujesz ją ze zmienną), musisz ją jawnie połączyć. Niektóre systemy operacyjne/kompilatory robią to za Ciebie, dlatego możesz nie zauważyć w przeszłości.

+2

+1 Wiele systemów automatycznie link do biblioteki matematycznej dla ciebie. Niektórzy nie. Twój nie. –

+11

Myślę, że on próbuje powiedzieć, że jeśli weźmie sqrt stałej, wynik jest również stałą, więc kompilator robi to za ciebie w czasie kompilacji, nie pozostawiając żadnych wywołań sqrt w kodzie, więc nie " t musi łączyć się z libm (-lm) ​​w czasie połączenia. –

+0

Południowa gościnność ma rację. –

Powiązane problemy