請問全域變數.值會自己歸0的問題 |
答題得分者是:brook
|
Cafia
一般會員 發表:6 回覆:12 積分:3 註冊:2003-03-17 發送簡訊給我 |
請教一下
我的project有兩個Form..分別由a.cpp及b.cpp控制
為了方便傳遞參數..我在a.h中宣告了一些全域變數及函數
並在a.cpp內完成函數的定義
但現在在b.cpp內要用這這些全域變數時
發現全都歸0了耶..
我檢查過確定中間沒有動到這些值啊..搞不懂耶~ 而且.我在b.cpp中include"a.h"..也在a.cpp中include"b.h"
編譯的時候都沒有錯誤和警告
但執行的時候..出現警告訊息..
所有的全域變數都分別在a.obj及b.obj中被定義了..
問題
1.為什麼全域變數在b.cpp中使用時都會變成0?
2.為什麼會有這樣的警告訊息?
|
brook
資深會員 發表:57 回覆:323 積分:371 註冊:2002-07-12 發送簡訊給我 |
|
Cafia
一般會員 發表:6 回覆:12 積分:3 註冊:2003-03-17 發送簡訊給我 |
|
miyu
中階會員 發表:13 回覆:96 積分:91 註冊:2003-05-01 發送簡訊給我 |
引言:雖然已經結案了, 可是我還是有點疑惑要吐嘈. 原作者並沒有把他的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出來叫) 以上是我的質疑引言: 有可能a和b各別存了一份資料,編譯未必會有警告,因為可以設某些警告不顯示. 我宣告全域變數的處理方式 1.在.cpp int AA; float BB; 2.在.h extern int AA; extern float BB;所以就是說如果全域變數的宣告部分,不能被重複include到.. 我剛測了這個的作法..真的就OK了 非常感謝~~ |
dllee
站務副站長 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
很好的質疑 最近常看到許多問題,提問者都沒有提供夠多的資料,或是有其他考量,只將部分訊息 > 我在一個專案中,的 class="code">
[Linker Warning] Public symbol '_abc' defined in both module C:\TEST\UNIT1.OBJ and C:\TEST\UNIT3.OBJ
[Linker Warning] Public symbol '_abc' defined in both module C:\TEST\UNIT1.OBJ and C:\TEST\UNIT4.OBJ
[Linker Warning] Public symbol '_abc' defined in both module C:\TEST\UNIT3.OBJ and C:\TEST\UNIT4.OBJ
只是,這樣的 Linker Warning 對於初學者來說,可能會『略過』,也許整個專案組譯下來有許多的 Warning 但只要執行檔有產出,對於初學者來說,也許就認為沒有問題了。其實,我倒是希望初學者能好好看一下這些警告訊息,如困警告訊息看不懂,可以提問呀。
以我寫的程式,也不百分之百沒有 Warning,只不過,每一個 Warning 我都知道是什麼 code 所造成,是否會對程式執行運作造成影響等等。
提供給初學者作為學習 BCB 的參考。 【註】
如果全部改成
static int abc;
則不會有任何的 Warning/Error Message。
因為,以我的認知 static 本來就是 local 的,只因為它放在整個 Unit 的 global 區,但它也只限此 Unit 使用,對於別的 Unit 有同樣的宣告並不會有任何影響。
身為程式設計師必需對程式負責,Compiler 只是輔助的工具而己! 沒空更新的網頁...
http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2003/08/06 08:44:13
------
http://www.ViewMove.com |
miyu
中階會員 發表:13 回覆:96 積分:91 註冊:2003-05-01 發送簡訊給我 |
引言: 很好的質疑 最近常看到許多問題,提問者都沒有提供夠多的資料,或是有其他考量,只將部分訊息 > >>< face="Verdana, Arial, Helvetica"> 還有一種更難聽的說法: 不知道問題在哪裡 ... 雖然這麼說很得罪人 XD引言: 我在一個專案中,的 Unit1,Unit3,Unit4.cpp 都加入了相同的 int abc; 的整體變數,組譯的結果是會發 Linker Warning,我所使用的 BCB 其 Error/Warning 都採用預設值。我還是覺得BCB在某些方面的策略過於寬鬆. 類似這種問題, 我很確定在gcc 2.95.4 (目前在用的版本), Visual Studio 6, 2002, 2003, By default Linker會直接吐一個error給你. 太寬鬆的策略對寫code的人並不是一種好事. 養成壞習慣以後很難改的 :X Well, 這是 BCB Linker 的策略問題... 反正基於某些理由, 我已經改用Delphi VC 了... 唉.引言: 【註】 如果全部改成 static int abc; 則不會有任何的 Warning/Error Message。 因為,以我的認知 static 本來就是 local 的,只因為它放在整個 Unit 的 global 區,但它也只限此 Unit 使用,對於別的 Unit 有同樣的宣告並不會有任何影響。C/C 的變數有所謂的領域視野. 或是反過來說, Compiler 是否可以找到它需要的 reference symbol. C/C 的變數也有所謂的生命週期, 另一種說法是, Compiler 為你所添加的 pseudo-code 該在什麼時候為這些變數alloc/release memory space及Init, 甚至是class的建構/解構時間點, 及順序問題. (請參考Modern C Design Ch.6 Implementing Singletons)引言: 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....哼哼, 很久沒去玩LiteStep了... 唉. 發表人 - Miyu 於 2003/08/06 12:42:28 |
dllee
站務副站長 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
每個 Compiler 有每個 Compiler 的優點,當然也有其缺點,不然,就不會各自有各自的愛好者。很高興,您已找到 Delphi + VC 良好開發環境。
說真的 Delphi 是比 BCB 更寬鬆,不是嗎
我則是選用 > <>沒空更新的網頁...
href="http://dllee.adsldns.org">http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |