看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《Trumen (真好多人)》之銘言: : 請問通常global variable會宣告在.cpp還是.h呢? : 之前曾經將global variable寫在.h : 但add Thread.cpp to project後compiler會出現warning訊息: : (ex: in main.h, int Variable = 0;) : [Linker Warning] Public symbol '_Variable' defined in both module D:\TRP : CODE\TRP 5.1\MAIN.OBJ and D:\TRP CODE\TRP 5.1\THREAD.OBJ : 後來查了網路,發現要寫成 : (in main.h) extern int Variable; : (in main.cpp) int Variable = 0; : 這樣子才不會有warning message產生,當中的原因是什麼呢? : 還有若是我將原本在main.h的變數改成 static int Variable = 0; : 也可以避免warning message產生,這又是為什麼呢? : (可以請問將variable設static的意義是?) : 謝謝! http://delphi.ktop.com.tw/board.php?cid=168&fid=912&tid=29349 找到問題所在了,分享一下~ ========================================================================= 原作者並沒有把他的Code List出來, 只說了他用了Global Value. 因此, 以這種描述, 有兩種可能的code. a.h, case 1 static int A; static int B; sttaic int C; a.h, case 2: int A; int B; int C; 但是, 因為你把變數宣告在 include file 裡. 要知道, # 開頭的 command 都會被 preprocessor 處理掉, 因此, 假設你寫的是: A.cpp: #include "a.h" int main(void) { ... return 0; } B.cpp: #include "a.h" void somefunc(void) { ... } 在 a.h case 1 裡, preprocessor 將會把程式展開像這樣: a.cpp: static int A; static int B; sttaic int C; int main(void) { ... return 0; } b.cpp: static int A; static int B; sttaic int C; void somefunc(void) { ... } 在 a.h case 2 裡, preprocessor 將會把程式展開像這樣: a.cpp: int A; int B; int C; int main(void) { ... return 0; } b.cpp: int A; int B; int C; void somefunc(void) { ... } 這兩個有什麼不一樣呢? 注意到那個 static 嗎? 根據C/C++語言規則, 定義為 static variable 的變數, 可視區 域僅限於宣告區域, 但是存在的壽命卻相當於 external variable 變數. 如果我沒記錯的話, static 變數的記憶空間配置是在程式載入初始時期 (就是 main() 被執行之前), 而他的內含值設定則是在該敘述第一次被執行到的時候, 且, 也只會設這 麼一次, 如果沒有指定特殊值, 則會被設定為零. 且這個記憶體將會保證在離開 main() 之前會一直都是存在的. 而另一種寫法叫作 external variable. 根據 C/C++ 語言規則, 凡是 external variable 變數, 其空間配置和內容初始化時期是在 main() 被執行前, 如果沒有指定特 殊值, 則會被設定為零. 且這個記憶體將會保證在離開 main() 之前會一直都是存在的. 如果是 external variable, 則無論你宣告多少次, 都應該只會有一份實體存在. 換句話 說, 你在 external variable 可視的領域內作了任何修改, 都應該反應到同一個記憶體 空間才對. 但是正常來說, external variable 大都宣告在實作檔 (.c/.cpp) 中, 然後在 header file 中宣告 extern type var_name, 然後含入這個 headrer file, 以便讓 compiler 知道有這一個 external variable. 或是說讓這個 external variable 的視野擴張到這 個實作檔裡. 如果說像 case 2 那樣寫, 沒有宣告 extern, 而是都宣告成 external variable 的話. 當編譯時期, compiler 只要看得到reference symbol 就好, 他才不管實際空間位置配置 , 所有實作檔中, symbol 是否重覆等問題. (只要同一個實作檔中沒有衝突, compiler就 不管) 前面說的問題是 linker 要去處理的. 因此, 理論上 case 2 的寫法, 應該會引發 link time error (或是 Warning, 這可能要看 error level 的設定, 或是 linker 的實作判 定). 所以我直覺認為, 原作者應該是採用 case 1 的寫法才對. 因為 case 2 的作法, 如果沒 有任何錯誤 (duplication symbol 一類的錯誤), 至少應該會有警告. 我實在不太相信 borland c++ 會這麼蠢, 連個警告都不給才是. (要是真的, 那我真的無 話可說...) case 1 的寫法, 你每一個 golbal variable 事實上都是不同的實體, 所以 compiler/linker都不會提出任何質疑. 不信的話你可以去dump symbol, 他們應該都會被冠上一些奇怪的前置名稱才對. (為了避 免linker出來叫) ============================================================================= 所以問題是在*.cpp include "main.h"時 main.h有global變數 使得所有*.cpp都會宣告該變數 所以在main.h內使用extern宣告變數的話,變數就不會重複定義了 而 static 本來就是 local 的,只因為它放在整個 *.cpp 的 global 區,但它 也只限此 *.cpp 使用,對於別的 *.cpp 有同樣的宣告並不會有任何影響。 以下是我的問題: 1. 如果用static宣告在main.h裡的變數的話 是否會變成所有*.cpp都會產生static變數呢? 這樣是不是有點占空間阿? (我只想要在main.cpp有此變數,用static寫法妥當嗎?) (因為我用extern會發生一些奇怪的問題...只能用static) 2. (跟global variabla無關的問題) 如果main.h 有#include "function.h" 則如果我把 function.h改成function.cpp 在main.h 變成#include "function.cpp" 前後會有什麼差嗎? 謝謝各位前輩不吝指教~! -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 122.126.97.143
tinlans:你查到的東西不完全說對,晚點吃完飯我用回文的。 06/09 21:23
tinlans:其實我還是比較建議你學這東西先翻教科書,少上網查。 06/09 21:23
tinlans:就像你在學校上英文課,老師不會叫你上網查文法一樣。 06/09 21:24