文章出處:http://www.52rd.com/blog/Detail_RD.Blog_apollo_2616.html
用extern修飾函數是表示被修飾的函數定義在當前檔案外,而該函數用extern宣告類型後就可以被當前檔案調用了。使用extern修飾某函數時,對該函數的調用是在串連階段才被處理的。下面我們看一段代碼。
/***********************************************
* fun.c
***********************************************/
#include <stdio.h>
void fun (int n)
{
printf("%d/n");
}
/***********************************************
* test.c
***********************************************/
extern void fun (void);
int main ()
{
fun();
return 0;
}
這兩個檔案能編譯串連到一起嗎?答案是肯定的,而且不會出現警告。那我們運行這個程式看看什麼結果:
C:/> test.exe
2367460
這個數從哪來的?不知道。這是因為我們調用了一個需要參數的函數而沒有傳遞參數給它,而這個函數還傻乎乎的以為傳過了參數,從寄存器裡讀出它的參數就去幹活了。那個寄存器裡是什麼值?誰也說不準。如果fun函數的參數是作為指標使用……,啊!麻煩大了!
要解決問題,對於上面的小程式,我們直接衝過去改掉就成了。但是如果你的程式裡有1000個檔案,平均每個檔案5000行(真正大的項目要比這大的多),那你還能一行行檢查下去嗎?如果調試過程中出了問題而你還不知道是這個原因導致的,如果你的程式很少運行到這個地方,……
所以,正確的方法是防患於未然,寫代碼是養成良好的習慣。
對於使用gcc的朋友,建議總是使用“-Wall”,“-Wall”是一個細心的秘書,他會及時提醒你代碼中存在的風險。
盡量避免使用extern修飾函數。一般情況下,如果我們希望某個函數可以被外界使用,就建立一個標頭檔,在其中聲明該函數的類型。哪個程式需要調用這個函數就把它的標頭檔包含進去。這樣一來如果調用的地方使用不當,在編譯階段就會提示錯誤,也節省了時間。而且,定義函數和聲明函數是同一個人做的,出錯的機會也就小了。