讀完《程序員的自我修養--鏈接、裝載和庫》相關章節,想來總結一下,若有錯誤,請指正,多謝。
你的工程里有很多xxx.c這樣的源文件,這些文件是文本文件,只有人能夠認識(當然編譯器認識),但是,cpu可不認識。問題就是,真正執行指令的是cpu。
讓編譯器翻譯一下(這里面有很多過程,這不是這篇文章的重點),一般來說,一個xxx.c文件就能翻譯成一個xxx.o,這就是目標文件了。
一個源文件就對應一個目標文件,這個目標文件就存儲了有關這個源文件的所有信息了,包括在這個源文件里函數的定義,全局變量的定義,等等。
但是,這樣就可以毫無憂慮地執行這個目標文件了么? 不可以。
一, 你這個目標文件可能沒有main函數;
二, 你這個目標文件里,可能用到了其他函數,而這些函數的定義是在其他目標文件里的。比如說,main.c 用到了 one.c 里的 void function(); 你去執行main.c 生成的main.o,肯定不行啊,因為cpu都找不到function在哪,從而function里存儲的指令,當然也沒法執行;
總之,你要運行的那個文件,里面必須得存有一切函數和變量的相關信息才可以。很顯然,目標文件不具有這個特性。因為,目標文件只存儲了自己的信息,并不知道其他目標文件的信息。
好的,你有一個main.c 和 一個 one.c, 并且成功的生成了兩個目標文件,各自存儲了自身的信息,它們就是 main.o 和 one.o。
不巧的是,main.c 里用到了 one.c 里的 void function(); 函數。這個時候,main.o 苦于找不到這個函數在哪而不得執行。而 one.o 靜靜的等在那,等待一個過程。
這個過程就是鏈接。
ld 是一個指令,linux 下,可以讓目標文件鏈接起來,拼成一個真正能用的可執行文件。
例如這樣:
ld main.o one.o -o go
其中 -o 后面是隨意指定的,這就是可執行文件的名稱。好了,這個 go 就是最終的可執行文件。你可以去執行它了。
go 是由兩個目標文件拼起來的,它當然知道所有的信息,包括 具體的 function 的指令。于是,它就可以被執行。
現在,到了這里,我們似乎忘了另一種重要的文件,頭文件。
好吧,問題能提升你看這篇文章的樂趣。那就思考一個問題:main.c 能成功編譯成 main.o么?
剛才的過程似乎太順利,main.c 刷一下就成了 main.o, 而問題是,你在 main.c 里使用了一個它不認得的函數 void function(); 這個竟然能編譯過,順利生成 main.o?
你可以試試,用這樣的命令:
gcc -c main.c -o main.o
-c 選項就是說,我要生成目標文件,而不是默認的可執行文件。你一定會得到一個【編譯】錯誤,這個錯誤會告訴你,function 這個函數我不認識,敗!
【編譯】錯誤,在源頭上先防止你造出一個完全不能用的程序。
這個時候,怎么辦,main.c 確實不認得 function 函數,你總不能把 one.c 里的函數復制粘貼到 main.c 里吧(當然這是可以的,不過,low爆了)。
那么需求如下:
一, 不拷貝過來整個函數;
二, 讓 main.c 順利生成 main.o。
問題的核心就是,讓 main.c 認識 function 是個啥(是函數還是變量?如果是函數,這個函數的參數有哪些?返回什么類型的值?)。
容易,你在 main.c 源文件里加一句
extern void function(); // 這個函數的返回類型是 void, 并且沒有參數。
這樣一來,main.c 本身就認識了 function, 注意,只是認識,但是并不知道它具體實現,也不知道這個函數在哪里。實際上,也不需要知道這么多。因為,我這一步只是生成目標文件而已。剩下的交給鏈接那一步。
結論,生成目標文件,必須得讓源文件認識每一個符號(變量和函數)。
假如 one.c 是你的同事編寫的,你應該讓他同時編寫一個頭文件。省的你還要在你的 main.c 里 一行行地加上
extern void function1();
extern int function2(char a);
...
...
這種東西。
你的同事會給你一個頭文件 one.h , 這個頭文件里實際上就是以上extern的內容。你只需要在 main.c 里這樣干:
#include "one.h"
就行了,這一句就是把 one.h 整個拷貝到 main.c 里去。
printf 用起來挺爽的。
你只用寫上
#include <stdio.h>
讓你的 main.c 認識這個函數就能用了。
不過,問題是,你并沒有鏈接 printf 所在的目標文件?。?/p>
思考,思考,再思考!
好吧,這不是個問題。
實際就是,gcc 默認幫你鏈接了。千萬不要認為,不用鏈接就可以?。。。?/p>
你可以這么認為:只要是系統提供的東西,你都不用手動鏈接,你關心好自己的東西就行了。
新聞熱點
疑難解答