2012-04-10 61 views
0

我正在編寫一個必須使用math.h中定義的pow函數的c項目。 當我試圖做這個項目時,gcc給出了以下鏈接錯誤: 未定義的對'pow'的引用。有關連接數學庫的一些問題

我知道-lm選項必須添加到我的鏈接指令中,但仍有幾個問題困擾着我。

Q1:當我將兩個常量傳入pow函數時,鏈接成功時沒有-lm。爲什麼? Q2:-lm處於鏈接指令的末尾或開始時會產生不同的結果。 gcc -lm $(OBJS)-o exbin是錯誤的,但是gcc $(OBJS)-o exbin -lm是正確的。爲什麼?

我使用的是Ubuntu 11.10和gcc 4.4.4。

謝謝!請原諒我的英語水池。

+0

爲了使用標準的math.h,你不需要任何特殊的鏈接器選項。 'pow'需要2個參數,這就是爲什麼當你正確使用它時它不會給你錯誤。 – Perception 2012-04-10 03:45:43

回答

0

我無法回答問題1(這看起來很奇怪),但對於問題2而言,gcc -lm $(OBJS) -o exbin不起作用的原因是因爲您必須按用法順序鏈接。這是最好的例子來解釋:

/* File func_a.h */ 
/* Declare func_a */ 
void func_a(); 

/* File func_a.c */ 
#include "func_a.h" 
void func_a() 
{ 
    /* do stuff */ 
} 

/* File func_b.c */ 
#include "func_a.h" 
void func_b() 
{ 
    /* Call func_a */ 
    func_a(); 
} 

正確鏈接func_afunc_b成可執行文件,則必須因爲func_b使用func_a它們連結成爲。總之,你總是希望最後鏈接你的庫函數。

1

編譯器知道pow(3, 4)或其他什麼,並通過在編譯時計算結果來優化程序,所以它不需要鏈接庫和運行庫。

鏈接器不會從庫中添加東西,除非它知道它需要它。對於靜態庫,這是完全正確的。對於共享庫,某些版本的編譯器會記錄所有共享庫中所有被讀取的符號,即使在掃描庫時不需要這些符號。如果在掃描時至少需要其中一個符號,則更新版本纔會使用共享庫。當庫來的時候,唯一需要的符號是main()(這就是爲什麼main()被指定爲宿主環境的起點),因此數學庫被忽略了,因爲它沒有需要的符號。