C语言多文件编译链接为1个可执行文件的简单原理
參考1:C header files and compilation/linking
參考2:計算機系統(tǒng)基礎(chǔ)(一)袁春風(fēng) (符號鏈接部分)
我們現(xiàn)在有一個簡單的工程,有這么幾個文件
1.t1.h
extern int x;void tt();現(xiàn)在,我們依次來看一下
- 頭文件 和 C源文件 如何聯(lián)系在一起
- 多文件如何變成1個可執(zhí)行目標(biāo)文件
預(yù)處理,組合頭文件與包含它的C源文件
在32位Linux系統(tǒng)中。
我們執(zhí)行g(shù)cc -E t1.c -o t1.i,對源程序進行預(yù)處理,將頭文件包含進來。
所謂預(yù)處理,就是將預(yù)編譯命令處理掉,比如,把頭文件的內(nèi)容拷貝到C源文件中,因此,我們就能夠理解.h和.c文件中全部變量的關(guān)系了,我們看一下生成的文件內(nèi)容
# 1 "t1.c" # 1 "<built-in>" # 1 "<command-line>" # 31 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 32 "<command-line>" 2 # 1 "t1.c" # 1 "t1.h" 1 extern int x;void tt(); # 2 "t1.c" 2int x;void tt(){x = 100; }可以看到,開始有一些記錄的信息,看起來應(yīng)該是注釋,是一些說明性信息。
然后我們看到,之前頭文件的內(nèi)容在這個文件里面了。如果你把它近似地看為一個源文件,你就能大概理解全局變量聲明和定義,以及不要重復(fù)定義等。
對于main.c文件的預(yù)處理,道理是一樣的
然后,我們將t1.i和main.i分別生成其可重定位目標(biāo)文件,最后鏈接起來,就生成了可執(zhí)行目標(biāo)文件。
gcc -c t1.i -o t1.o # 生成可重定位目標(biāo)文件 gcc -c main.i -o main.o # 生成可重定位目標(biāo)文件 gcc -o main main.o t1.o # 鏈接,生成可執(zhí)行目標(biāo)文件 ./main # 運行可執(zhí)行目標(biāo)文件最后,需要說明
對于函數(shù)的聲明(頭文件聲明、外部聲明、內(nèi)部聲明)與定義(內(nèi)部定義、外部定義)
在c源文件中進行函數(shù)聲明,然后使用它,在鏈接的時候,這個聲明的函數(shù)(但未在該文件中定義)鏈接器會自動在其他的可重定位目標(biāo)文件中尋找其定義,如果找到了就聯(lián)系起來,否則就報錯。這就意味著,所有的C源文件中的函數(shù)默認(rèn)都是全局的,你可以在模塊1聲明函數(shù)a,然后調(diào)用它,在模塊2中定義函數(shù)a,之后將兩個模塊鏈接起來生成可執(zhí)行文件。
好吧,每次都聲明很麻煩,所以,我們在模塊2對應(yīng)的頭文件聲明,然后模塊1引入頭文件,這樣,我們就能夠進行和之前一樣的操作了,你知道的,頭文件在預(yù)處理的時候會被包含進入源文件,這樣,其實達到了和我們手動聲明一樣的效果。
如果你不想讓函數(shù)是全局的,那就加上static,這樣,只有該源文件可以使用它了!
對于變量的定義與初始化
- 局部變量:只能在其{ }內(nèi)使用
- static變量:只能在本模塊內(nèi)使用
- 全局變量:全部都可以用
- 本模塊定義
- 外部定義extern
對于本模塊使用的,沒得說,就是只有這個源文件能夠使用這個變量!
只討論全局變量。
因此說,使用全局變量,最好
- 初始化全局變量
- 只定義一次
- 其他的模塊如果要用,就聲明extern表示引用外部定義,而不是再聲明一個弱符號(不是不行,但是這樣的話,gcc能用,VS就不能用)
- 不要在頭文件定義全局變量(頭文件被多次包含的話…得定義多少次,恐怖)
注意
函數(shù)有
對于任何模塊,必須先聲明,再使用,聲明之后可以不定義,因為可以外部定義,但是被聲明被使用的函數(shù),必須有其定義。 要是聲明之后沒有使用也沒有定義,其實也行,但是最好不要這樣干,太奇怪了!
對于同一模塊,先定義再使用也可以,但是不能先使用再定義,順序很重要。
變量有
- 是否定義
- 是否初始化
- 是否使用
然后,還涉及到不同模塊之間…
總結(jié)
以上是生活随笔為你收集整理的C语言多文件编译链接为1个可执行文件的简单原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lol官方助手怎么下载为什么我下载的是腾
- 下一篇: 如何掌握java API的方法