extern void a(void)和#include "a.h"的差別? |
尚未結案
|
h2
一般會員 發表:1 回覆:2 積分:0 註冊:2004-10-04 發送簡訊給我 |
|
richtop
資深會員 發表:122 回覆:646 積分:468 註冊:2003-06-10 發送簡訊給我 |
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 發送簡訊給我 |
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 發送簡訊給我 |
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 發送簡訊給我 |
引言: // 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 發送簡訊給我 |
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 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |