C語言__static和extern關鍵字
C語言__static和extern關鍵字
static和extern不僅可以用在變數上,還可以用在函式上。這講先介紹它們對函式的作用。
extern與函式
如果一個程式中有多個原始檔(.c),編譯成功會生成對應的多個目標檔案(.obj),這些目標檔案還不能單獨執行,因為這些目標檔案之間可能會有關聯,比如a.obj可能會呼叫c.obj中定義的一個函式。將這些相關聯的目標檔案連結在一起後才能生成可執行檔案。
外部函式:如果在當前檔案中定義的函式允許其他檔案訪問、呼叫,就稱為外部函式。C語言規定,不允許有同名的外部函式。
內部函式:如果在當前檔案中定義的函式不允許其他檔案訪問、呼叫,只能在內部使用,就稱為內部函式。C語言規定不同的原始檔可以有同名的內部函式,並且互不干擾。
編譯完成後需要連線後才能執行,連線外部函式就是此刻我們的問題,在C語言標準裡面直接使用外部函式是報錯的,因為函式並不知道你的這個外部函式在哪裡宣告定義的,當然不可能直接使用。
那麼我們匯入外部函式所在的檔案可以嗎?答案是不可以,檔案包含僅僅只是相當於字串拷貝,這樣的後果就是我們產生了同名的外部函式,C語言不允許同名外部函式存在,不然在連線的時候就不知道該連線那個檔案了。
正確的做法是我們在使用外部函式的時候在主函式前面宣告外部函式就行了,宣告外部函式: extern 函式名 (引數列表);但是這樣做在大型的專案裡面超級的麻煩,所以我們一般會定義一個頭檔案,然後在標頭檔案當中宣告外部函式,把檔案包含在主程式內就可以了。需要了解的是extern關鍵字不寫沒關係,因為不寫預設就是extern。
static與函式
宣告內部函式
static void one(); // 就是宣告one函式是個內部函式。
定義內部函式
static void one() // 定義了內部函式 也稱之為靜態函式 外部不可以使用
{
函式語句;
}
編譯、連結解惑
所謂編譯,就是單獨檢查每個原始檔的語法是否合理,並不會檢查每個原始檔之間的關聯關係,一個原始檔編譯成功就生成一個目標檔案。
所謂連結,就是檢查目標檔案的關聯關係,將相關聯的目標檔案組合在一起,生成可執行檔案。
static、extern與函式的總結
* 在定義函式時,在函式的最左邊加上static可以把該函式宣告為內部函式(又叫靜態函式),這樣該函式就只能在其定義所在的檔案中使用。如果在不同的檔案中有同名的內部函式,則互不干擾。* static也可以用來宣告一個內部函式
* 在定義函式時,如果在函式的最左邊加上關鍵字extern,則表示此函式是外部函式,可供其他檔案呼叫。C語言規定,如果在定義函式時省略extern,則隱含為外部函式。
* 在一個檔案中要呼叫其他檔案中的外部函式,則需要在當前檔案中用extern宣告該外部函式,然後就可以使用,這裡的extern也可以省略。
static與全域性變數
在Java中,全域性變數的定義沒有嚴格的位置規定
在C語言中,全域性變數定義的位置是有限制的。預設情況下,一個函式不可以訪問在它後面定義的全域性變數。要麼在main函式之前定義,要麼在main函式之前宣告(extern是用來宣告一個已經定義過的變數。)
在另一個原始檔中也有全域性變數int a;,那麼這兩個原始檔的所有全域性變數int a;都代表著同一個變數。
在全域性變數前加static修飾符這表明了該變數為靜態全域性變數,其他檔案的函式不可以使用,只可以在本檔案下使用。