作者Trumen (真好多人)
看板C_and_CPP
標題Re: [問題] global variable的問題
時間Wed Jun 9 10:14:55 2010
※ 引述《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