線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:6460
推到 Plurk!
推到 Facebook!

extern void a(void)和#include "a.h"的差別?

尚未結案
h2
一般會員


發表:1
回覆:2
積分:0
註冊:2004-10-04

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-10-04 11:16:44 IP:61.220.xxx.xxx 未訂閱
請教一下 C語言中 若為了要使用其他人寫的函式庫, 舉例來說,在我的C檔案中使用extern void a(void)和#include "a.h"有差別嗎? 另一個問題 a.h中的a函式的phototype該寫成 void a(void);還是extern void a(void); 謝謝指教
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-10-04 22:56:48 IP:211.76.xxx.xxx 未訂閱
h2 您好:    底下整理了,呼叫外部.c或.cpp中的變數與函式供您參考。    
// file: shareC.h    extern int dataInC;    extern "C" {  // 避免在.cpp中為實現同名異式(overload),會更改函式名稱。
  void funInC();
  int  funInC1(int x);
};  
//=============================================    // file: shareC.h    int dataInC = 44;    int funInC()
{ return dataInC;
}    int funInC1(int x)
{ return (x*x 3);
}
//=============================================    // file: shareCPP.h    extern float dataInCPP;    extern float funInCPP(float x); //不加extern亦可,compiler在該程式中找不到函式內容,會認定這是個外部函式。
//=============================================    // file: shareCPP.cpp    float dataInCPP = 88;     float funInCPP(float x)
{ if ( x<0 ) 
    return (-x);
  else  return (x);
}
//=============================================    要使用shareC.c時,需要include "shareC.h";
要使用shareCPP.cpp時,需要include "shareCPP.h"。
通常程式的實作部份放在.c或.cpp中,而其相對的.h或.hpp則是提供他人在使用該.c或.cpp時,能正確的引用所提供的變數與函式;
如果因為某種因素,您不希望實作部份公開,則可僅將.obj與對應的.h或.hpp提供別人使用即可。
一則保有您的原始碼,二來可以讓他人正確使用您的開發成果。 
RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====##### 發表人 - richtop 於 2004/10/04 23:03:32
h2
一般會員


發表:1
回覆:2
積分:0
註冊:2004-10-04

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-10-05 09:58:15 IP:61.220.xxx.xxx 未訂閱
richtop: 感謝你的回應和指導.... 這幾天也看了不少你的文章...    關於我的問題我還有些疑問 以你的C例子而言(抱歉我非資工、科出身的,程式底子不好...也沒學過C++)    // file: shareC.h    extern int dataInC;    extern "C" {  // 避免在.cpp中為實現同名異式(overload),會更改函式名稱。   void funInC();  // 問題一:請問我要給外部用的這裡需要加extern嗎?(如extern int funInC(); ) int funInC1(int x); }; //============================================= // file: shareC.h int dataInC = 44; int funInC() { return dataInC; } int funInC1(int x) { return (x*x 3); } 問題二: 若我現在有一個專案包含main.c和shareC.c和shareC.h main.c需要用到funInC() 那我試過可以在main.c內開頭加入 #include "shareC.h" 或 extern int funInC(); 這兩個方式都可以compile過 也都可以WORK 但是想知道這兩種方式有好壞之分這類的較深入的評析嗎? 有用哪一種方式比較好嗎? 謝謝指教
暗黑破壞神
版主


發表:9
回覆:2301
積分:1627
註冊:2004-10-04

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-10-05 20:53:27 IP:221.169.xxx.xxx 未訂閱
t首先,你先把你自己當做compiler來看你的程式。 你會怎麼做? //file_c.h main() { f1(); }    當你讀到f1();這一行時,你會不會不知道它是個什麼東西? 因為沒有任何說明它是做什麼用的,以及它的傳回值是什麼型別(int or char or char *.....)更沒說它有多少個參數,參數型別又是什麼。 請問。你要怎麼處理?    所以。我們必須”教”compiler認識 f1()這個函數。 所以我們可以寫成這樣。    //file_c.c void f1(void) { return; }    main() { f1(); }    好了。這樣子。你是不是就可以很清楚知道。。。喔。。f1()是這樣的東西。所以等妳讀到main()裏面的f1();時就不會產生問題了?    再來,我們會發現,如果我們有很多的函數。f1(), f2(), f3().......交錯呼叫。而我們老是把main()放到後面去。當然啦。 身為compiler的你。有一目十行過目不忘的功力。 可是身為寫程式的程式設計師。可就沒這個本事了。 所以,我們會把它寫成: //file_c.c void f1(void); void f2(void); void f3(void); . . . main() { f1(); }    void f1(void) { }    void f2(void) {}    void f3(void) {} ....    這種方式。 也就是讓compiler 先知道說 f1(), f2(), f3() 這些函數的”長相” 讓它在讀main()時。不會產生問題。    好啦。。。。。講到這裏,好像還沒有講到#include 吧 當你的程式又越來越大。越來越大。。。。。。你會發現在main前面的 void f1()......fn(); 的宣告變成一長串了。 這時候你就會很煩的把它們移出去。變成另一個檔案。 而這時候。這個檔案就會是這樣。 // file_h.h void f1(); void f2(); void f3();    而你的程式檔呢,會變成 // file_c.c #include "file_h.h" main() { f1(); }    void f1(void){}; void f2(void){}; ........    這樣是不是看起來簡單多了?既讓compiler讀得懂你的程式。又讓程式設計師不會看一堆”教”compiler 的宣告呢?    再來當你的 file_c.c 的 void f1(void).........這一類的函數又多到讓你的.C檔案太大了。你就會再想去切割它。 讓它變小。 這時候,有關係的是linker 這不在你的發問裏。就帶過了。    而你有另一個問題就是 extern void f(void); 跟 void f(void); 有沒有什麼不同喔。 基本上,這個沒什麼差。都可以。    extern 主要用在變數的宣告用。不是在函數的宣告用。 如果是 int a; extern int a; 這就有差了。 int a; 表示a這個數,是在目前這個.c的檔案中宣告的。 extern int a; 表示要教compiler知道說,我用到一個叫做a 的整數。而這個整數不在這個.c的檔案裏。你先別管我a放在那邊。那是linker 要管的。 而你會在另一個.c的檔案中宣告 int a;    打了半天。不知道您看懂了沒有。^_^
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-10-05 22:49:05 IP:211.76.xxx.xxx 未訂閱
引言: // file: shareC.h extern int dataInC; extern "C" { // 避免在.cpp中為實現同名異式(overload),會更改函式名稱。 void funInC(); // 問題一:請問我要給外部用的這裡需要加extern嗎?(如extern int funInC(); ) int funInC1(int x); 不好意思,寫的太快!其實比較好的寫法是加上extern。這可以明確讓compiler或閱讀程式的人清楚知道,這個函式是在另外一個程式中。 您問的好,有一點忘了說明,其實有沒有加extern還有一點差別: 比方說在C/C 中,如果您呼叫一個在之後才明確定義(有完整的程式內容)的函式,會出現找不到該函式的錯誤。這時變通的方法是,將該函式移到呼叫它的程式碼之前,或者就是先宣告它的原型但不必完整將程式碼列出,例如說:void funInC();,但這時就可以不要加上extern了(不過即是加了也可以,在BCB中是如此)。 所以我的結論是:對於一個函式,在使用前compiler必須知道其真正的原型,這樣才能預留適當的位置(傳回型態與形式參數),等到真正連結(Link)時,再將其填入預留的位置裡。所以這個函式是在原程式中或外部程式裡都沒有關係,對compiler來說,它預留了存放該函式的位置,至於這個函式是否存在,那就得在經過連結之後才能完全確定,畢竟外部程式有可能不是我們自己寫的,也有可能給的是錯誤的程式,這樣在連結時就會產生錯誤訊息。 在BCB的線上說明提到:"The keyword extern is optional for a function prototype.",也能支持這樣的說法。 }; //============================================= // file: shareC.h int dataInC = 44; int funInC() { return dataInC; } int funInC1(int x) { return (x*x 3); }
RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====#####
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-10-05 23:04:54 IP:211.76.xxx.xxx 未訂閱
h2 您好:    因存不下去,所以在續一篇。 問題二: 若我現在有一個專案包含main.c和shareC.c和shareC.h main.c需要用到funInC() 那我試過可以在main.c內開頭加入 #include "shareC.h" 或 extern int funInC(); 這兩個方式都可以compile過 也都可以WORK 但是想知道這兩種方式有好壞之分這類的較深入的評析嗎? 有用哪一種方式比較好嗎? 使用include其實就是把該.h或.hpp的內容複製進目前的程式裡(也與當中的編譯指令相關),所以如果您不用include而是自己打當然意思也是一樣,只是通常我們不可能知道這些函式的真正原型。透過提供的.h或.hpp檔能正確的引用這些函式,同時也能經此了解函式的傳回值與參數的型態。應該是比較好的方式。
h2
一般會員


發表:1
回覆:2
積分:0
註冊:2004-10-04

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-10-06 09:26:53 IP:61.220.xxx.xxx 未訂閱
Dear RichTop, 感謝您精闢的解說... 受惠良多 h2
系統時間:2024-05-03 0:38:15
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!