1.簡單的C語言程序(項目)只有一個C文件振惰,編譯的時候gcc a.c -o a痒蓬,執(zhí)行的時候./a
2.復(fù)雜的C語言程序(項目)由是由多個C文件構(gòu)成的舀患,比如一個項目中包含2個C文件(a.c, b.c ),編譯的時候用gcc a.c b.c -o ab察蹲,執(zhí)行的時候./ab
在a.c和b.c中分別定義main函數(shù),各自單獨編譯時沒問題催训,但是兩個文件作為一個項目來編譯gcc a.c b.c -o ab的時候洽议,就會報錯(multiple definition of 'main')。為什么會報錯漫拭?因為a.c和b.c這時候組成了一個程序亚兄,而一個程序必須有且只有一個main函數(shù)。
3.為什么需要多文件項目采驻?為什么不在一個.c文件中寫完所有的功能审胚?
因為一個真正的C語言項目是很復(fù)雜的,包含很多個函數(shù)礼旅,寫在一個文件中不利于查找膳叨、組織、識別痘系,所以人為的將復(fù)雜項目中的很多函數(shù)菲嘴,分成了一個一個的功能模塊,然后分開放在不同的.c文件中,于是有了多文件項目龄坪。
所以昭雌,在b.c中定義的一個函數(shù),很可能a.c中就會需要調(diào)用健田。你在任何一個文件中定義的任何一個函數(shù)烛卧,都有可能被其他任何一個文件中的函數(shù)來調(diào)用。但是大家最終都是被main函數(shù)調(diào)用的妓局,有可能直接調(diào)用唱星,也可能是間接調(diào)用。間接調(diào)用指的是main函數(shù)內(nèi)的一個函數(shù)里調(diào)用了其他函數(shù)跟磨。
4.多文件項目中间聊,跨文件調(diào)用函數(shù)
在調(diào)用函數(shù)前,要先聲明該被調(diào)用函數(shù)的原型抵拘。只要在調(diào)用前聲明了該函數(shù)哎榴,那么調(diào)用時就好像這個函數(shù)是定義在本文件中的函數(shù)一樣。
總結(jié):函數(shù)使用的三大要素——函數(shù)定義僵蛛、函數(shù)聲明尚蝌、函數(shù)調(diào)用
(1)如果沒有定義,只有聲明和調(diào)用充尉,編譯時會報連接錯誤飘言。(undefined reference to 'func_nxx')
(2)如果沒有聲明,只有定義和調(diào)用驼侠,編譯時一般會報警告姿鸿,極少數(shù)情況下不會報警告。但是最好加上聲明倒源。
(3)如果沒有調(diào)用苛预,只有定義和聲明,編譯時一般會報警告(有一個函數(shù)沒有使用)笋熬,有時不會報警告热某。這時候程序執(zhí)行不會出錯,只是你白白寫了幾個函數(shù)胳螟,而沒有使用浪費掉而已昔馋。
5.跨文件的變量引用
(1)在a.c中定義的全局變量,在a.c中可以使用糖耸,在b.c中不可以直接使用秘遏,編譯時報錯error:'g_a' undeclared。
(2)想在b.c中使用a.c中定義的全局變量蔬捷,有一個間接的使用方式垄提,在a.c中寫一個函數(shù),然后函數(shù)中使用a.c中定義的該全局變量周拐,然后在a.c中先聲明函數(shù)铡俐,再使用函數(shù),即可達(dá)到在b.c中間接引用a.c中變量的目的妥粟。
(3)想在b.c中直接引用a.c中定義的全局變量g_a的聲明审丘,這句話告訴編譯器,我再外部C程序中(不是本文件的另一個文件)某個地方定義了一個全局變量int g_a勾给,而且我現(xiàn)在要在這里引用(extern int g_a)它告訴編譯器一聲滩报,不用報錯了。
(4)情況分析
① 情況一:我只在b.c中聲明變量播急,但是別的文件中根本就沒定義這個變量脓钾,會怎樣?
→編譯器報錯(連接錯誤)
不管是函數(shù)還是變量桩警,都有定義可训、聲明、引用三要素捶枢。其中握截,定義時創(chuàng)造這個變量或函數(shù),聲明是向編譯器交代它的原型烂叔,引用是使用這個變量或函數(shù)谨胞。所以,如果沒有定義只有聲明和引用蒜鸡,編譯器一定會報錯胯努。
②情況二:在a.c中定義了全局變量g_a,但是b.c中沒有聲明g_a逢防,引用該變量會怎樣康聂?
→直接報錯,未定義
③情況三:在a.c中定義胞四,在b.c中聲明恬汁,a.c和b.c都沒有引用。
→浪費了辜伟,未報錯氓侧。
(5)在一個程序里面,一個函數(shù)可以定義一次导狡,引用可以有無數(shù)次约巷,聲明也可以有無數(shù)次。因為函數(shù)定義或者變量定義實際上是創(chuàng)造了這個函數(shù)旱捧、變量独郎,所以只能有一次踩麦。(多次創(chuàng)造同名的變量會造成變量名重復(fù)、沖突氓癌,多次創(chuàng)造同名的函數(shù)也會造成函數(shù)名重復(fù)谓谦、沖突)。聲明是告訴編譯器變量/函數(shù)的原型贪婉,在每個引用了這個全局變量/函數(shù)的文件之前都要聲明該變量/函數(shù)反粥。
(6)問題一:局部變量能不能跨文件使用?
不能疲迂。因為局部變量屬于代碼塊作用域才顿,它的作用域只有他定義的那個函數(shù)內(nèi)部。
問題二:靜態(tài)局部變量能不能跨文件使用尤蒿?
不能郑气。因為本質(zhì)上還是個局部變量。
6.頭文件的引入
從之前可以看到腰池,函數(shù)的聲明是很重要的竣贪。當(dāng)我們在一個龐大的項目中,有很多個源文件巩螃,每個源文件中都有很多函數(shù)并且需要在各個文件中相互穿插引用函數(shù)演怎,怎么解決函數(shù)的聲明問題?
頭文件避乏。如把聲明放在a.h文件里爷耀,頭文件引用#include "a.h"。
(1)#inlcude包含頭文件時拍皮,用<>和""的區(qū)別
<>用來包含系統(tǒng)自帶的頭文件歹叮,系統(tǒng)自帶指的是,不是你寫的铆帽,是編譯器或者庫函數(shù)或者操作系統(tǒng)提供的頭文件咆耿。""用來包含項目目錄中的頭文件,這些一般是自己寫的爹橱,當(dāng)前目錄查找萨螺。
(2)防止重復(fù)包含頭文件
#ifdef __A_H__
#define __A_H__
//C語言頭文件的聲明
#endif
注意:不要在頭文件中定義變量,這樣容易重復(fù)定義愧驱,因為頭文件容易被許多源文件包含慰技。