国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 課堂 > 電腦知識(shí) > 正文

linux下c程序的鏈接、裝載和庫(kù)(1)

2024-05-08 15:56:04
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  讀完《程序員的自我修養(yǎng)--鏈接、裝載和庫(kù)》相關(guān)章節(jié),想來(lái)總結(jié)一下,若有錯(cuò)誤,請(qǐng)指正,多謝。

1. 什么叫目標(biāo)文件?

    你的工程里有很多xxx.c這樣的源文件,這些文件是文本文件,只有人能夠認(rèn)識(shí)(當(dāng)然編譯器認(rèn)識(shí)),但是,cpu可不認(rèn)識(shí)。問(wèn)題就是,真正執(zhí)行指令的是cpu。

    讓編譯器翻譯一下(這里面有很多過(guò)程,這不是這篇文章的重點(diǎn)),一般來(lái)說(shuō),一個(gè)xxx.c文件就能翻譯成一個(gè)xxx.o,這就是目標(biāo)文件了。

    一個(gè)源文件就對(duì)應(yīng)一個(gè)目標(biāo)文件,這個(gè)目標(biāo)文件就存儲(chǔ)了有關(guān)這個(gè)源文件的所有信息了,包括在這個(gè)源文件里函數(shù)的定義,全局變量的定義,等等。

    但是,這樣就可以毫無(wú)憂慮地執(zhí)行這個(gè)目標(biāo)文件了么?   不可以。

    一, 你這個(gè)目標(biāo)文件可能沒(méi)有main函數(shù);

    二, 你這個(gè)目標(biāo)文件里,可能用到了其他函數(shù),而這些函數(shù)的定義是在其他目標(biāo)文件里的。比如說(shuō),main.c 用到了 one.c 里的 void function(); 你去執(zhí)行main.c 生成的main.o,肯定不行啊,因?yàn)閏pu都找不到function在哪,從而function里存儲(chǔ)的指令,當(dāng)然也沒(méi)法執(zhí)行;

    總之,你要運(yùn)行的那個(gè)文件,里面必須得存有一切函數(shù)和變量的相關(guān)信息才可以。很顯然,目標(biāo)文件不具有這個(gè)特性。因?yàn)椋繕?biāo)文件只存儲(chǔ)了自己的信息,并不知道其他目標(biāo)文件的信息。

2. 目標(biāo)文件的拼接-->可執(zhí)行文件

    好的,你有一個(gè)main.c 和 一個(gè) one.c, 并且成功的生成了兩個(gè)目標(biāo)文件,各自存儲(chǔ)了自身的信息,它們就是 main.o 和 one.o。

    不巧的是,main.c 里用到了 one.c 里的 void function(); 函數(shù)。這個(gè)時(shí)候,main.o 苦于找不到這個(gè)函數(shù)在哪而不得執(zhí)行。而 one.o 靜靜的等在那,等待一個(gè)過(guò)程。

    這個(gè)過(guò)程就是鏈接。 

    ld 是一個(gè)指令,linux 下,可以讓目標(biāo)文件鏈接起來(lái),拼成一個(gè)真正能用的可執(zhí)行文件。

    例如這樣:

    ld main.o one.o -o go

    其中 -o 后面是隨意指定的,這就是可執(zhí)行文件的名稱。好了,這個(gè) go 就是最終的可執(zhí)行文件。你可以去執(zhí)行它了。

    go 是由兩個(gè)目標(biāo)文件拼起來(lái)的,它當(dāng)然知道所有的信息,包括 具體的 function 的指令。于是,它就可以被執(zhí)行。

    現(xiàn)在,到了這里,我們似乎忘了另一種重要的文件,頭文件。

3. 頭文件是個(gè)啥?

    好吧,問(wèn)題能提升你看這篇文章的樂(lè)趣。那就思考一個(gè)問(wèn)題:main.c 能成功編譯成 main.o么?

    剛才的過(guò)程似乎太順利,main.c 刷一下就成了 main.o, 而問(wèn)題是,你在 main.c 里使用了一個(gè)它不認(rèn)得的函數(shù) void function(); 這個(gè)竟然能編譯過(guò),順利生成 main.o?

    你可以試試,用這樣的命令:

    gcc -c main.c -o main.o

    -c 選項(xiàng)就是說(shuō),我要生成目標(biāo)文件,而不是默認(rèn)的可執(zhí)行文件。你一定會(huì)得到一個(gè)【編譯】錯(cuò)誤,這個(gè)錯(cuò)誤會(huì)告訴你,function 這個(gè)函數(shù)我不認(rèn)識(shí),敗!

    【編譯】錯(cuò)誤,在源頭上先防止你造出一個(gè)完全不能用的程序。

    這個(gè)時(shí)候,怎么辦,main.c 確實(shí)不認(rèn)得 function 函數(shù),你總不能把 one.c 里的函數(shù)復(fù)制粘貼到 main.c 里吧(當(dāng)然這是可以的,不過(guò),low爆了)。

    那么需求如下:

    一, 不拷貝過(guò)來(lái)整個(gè)函數(shù);

    二, 讓 main.c 順利生成 main.o。

    問(wèn)題的核心就是,讓 main.c 認(rèn)識(shí) function 是個(gè)啥(是函數(shù)還是變量?如果是函數(shù),這個(gè)函數(shù)的參數(shù)有哪些?返回什么類型的值?)。

    容易,你在 main.c 源文件里加一句 

    extern void function(); // 這個(gè)函數(shù)的返回類型是 void, 并且沒(méi)有參數(shù)。

    這樣一來(lái),main.c 本身就認(rèn)識(shí)了 function, 注意,只是認(rèn)識(shí),但是并不知道它具體實(shí)現(xiàn),也不知道這個(gè)函數(shù)在哪里。實(shí)際上,也不需要知道這么多。因?yàn)椋疫@一步只是生成目標(biāo)文件而已。剩下的交給鏈接那一步。

    結(jié)論,生成目標(biāo)文件,必須得讓源文件認(rèn)識(shí)每一個(gè)符號(hào)(變量和函數(shù))。

    假如 one.c 是你的同事編寫(xiě)的,你應(yīng)該讓他同時(shí)編寫(xiě)一個(gè)頭文件。省的你還要在你的 main.c 里 一行行地加上 

    extern void function1();

    extern int function2(char a);

    ...

    ...

    這種東西。

    你的同事會(huì)給你一個(gè)頭文件 one.h , 這個(gè)頭文件里實(shí)際上就是以上extern的內(nèi)容。你只需要在 main.c 里這樣干:

    #include "one.h"

    就行了,這一句就是把 one.h 整個(gè)拷貝到 main.c 里去。

4. PRintf 用起來(lái)挺爽的。

    printf 用起來(lái)挺爽的。

    你只用寫(xiě)上

    #include <stdio.h>

    讓你的 main.c 認(rèn)識(shí)這個(gè)函數(shù)就能用了。

    不過(guò),問(wèn)題是,你并沒(méi)有鏈接 printf 所在的目標(biāo)文件啊!

    思考,思考,再思考!

    好吧,這不是個(gè)問(wèn)題。

    實(shí)際就是,gcc 默認(rèn)幫你鏈接了。千萬(wàn)不要認(rèn)為,不用鏈接就可以!!!!

    你可以這么認(rèn)為:只要是系統(tǒng)提供的東西,你都不用手動(dòng)鏈接,你關(guān)心好自己的東西就行了。

 


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 武定县| 邳州市| 宁国市| 商水县| 峨边| 长寿区| 塘沽区| 夏津县| 安仁县| 汤阴县| 克什克腾旗| 田林县| 罗田县| 青龙| 咸宁市| 达孜县| 明水县| 霍山县| 湘潭市| 冷水江市| 尼玛县| 郯城县| 东方市| 重庆市| 南宫市| 进贤县| 高唐县| 馆陶县| 上蔡县| 武强县| 南投县| 崇左市| 山东| 靖西县| 准格尔旗| 桐乡市| 磐安县| 石城县| 微山县| 佛教| 泰宁县|