[問題] 外部變數static問題

看板C_and_CPP作者 (Orah~)時間8年前 (2017/08/04 09:18), 8年前編輯推噓2(2020)
留言22則, 5人參與, 最新討論串1/1
開發平台(Platform): (Ex: Win10, Linux, ...) Linux 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) GCC 問題(Question): 最近在c primer plus中看到一段有關使用全域變數的一種方法 /* constant.h -- defines some global constants */ static const double PI = 3.14159; static const char * MONTHS[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; /* file1.c -- use global constants defined elsewhere */ #include "constant.h" /* file2.c -- use global constants defined elsewhere */ #include "constant.h" 書上說不使用static關鍵字,那麼包含在file1.c和file2.c檔案中的constant.h將會導 致每個使用相同識別符號所定義宣告的檔案,都不被ANSI標準所支援 想知道是那邊違反標準?因為就算沒有使用static編譯執行似乎也沒有錯誤? 在這麻煩各位 感謝 程式碼(Code):(請善用置底文網頁, 記得排版) http://ideone.com/jLsWKu 補充說明(Supplement): 原文圖片:http://imgur.com/a/npcsk -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.82.152.86 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1501809537.A.F43.html ※ 編輯: Tverous (111.82.152.86), 08/04/2017 09:20:50

08/04 09:32, , 1F
你沒有加static又給多個.c檔include應該就會link error
08/04 09:32, 1F

08/04 09:35, , 2F
compile 的下一步是 link, 如果沒有用 static 指定
08/04 09:35, 2F

08/04 09:35, , 3F
是 internal linkage, 可能會造成識別符名稱的汙染
08/04 09:35, 3F

08/04 10:45, , 4F
想請問汙染具體來說是怎樣?因為假如使用個區域變數不是
08/04 10:45, 4F

08/04 10:46, , 5F
就直接隱藏掉全域變數嘛?
08/04 10:46, 5F

08/04 11:35, , 6F
沒有用static修飾的file-scope變數是external linkage
08/04 11:35, 6F

08/04 11:36, , 7F
這表示它可以被任何編譯單元參考到
08/04 11:36, 7F

08/04 11:36, , 8F
以你的例子而言 file1跟file2會各有一個變數定義
08/04 11:36, 8F

08/04 11:36, , 9F
假設沒有用static修飾 當程式中使用到該變數時
08/04 11:36, 9F

08/04 11:36, , 10F
linker會不知道要將其鏈結到哪個變數定義
08/04 11:36, 10F

08/04 11:36, , 11F
相對來說 若是加了static 在file1中的變數定義
08/04 11:36, 11F

08/04 11:37, , 12F
就只會在file1中使用時被看見 file2同理
08/04 11:37, 12F

08/04 11:37, , 13F
至於你會沒有遇到錯誤 可能是你個別編譯兩個檔案
08/04 11:37, 13F

08/04 11:37, , 14F
並且沒有鏈結它們 又或是像書中所寫
08/04 11:37, 14F

08/04 11:37, , 15F
鏈結器幫你做了不合標準的額外處理
08/04 11:37, 15F

08/04 12:15, , 16F
大概了解了 感謝各位前輩
08/04 12:15, 16F

08/05 01:18, , 17F
題外話其實C標準J.5.11 Multiple External Definition有特別
08/05 01:18, 17F

08/05 01:18, , 18F
提到很多實作都會支援可以多個定義 只要不打架就好
08/05 01:18, 18F

08/05 01:20, , 19F
例如全域變數如果沒有初始化gcc會預設把他們都丟到common
08/05 01:20, 19F

08/05 01:20, , 20F
section內 而linker會把所有object file的common symbol合併
08/05 01:20, 20F

08/05 01:22, , 21F
所以就算有多個定義只要大小一樣也是ok的
08/05 01:22, 21F

08/05 01:23, , 22F
這個功能可以在編譯的時候下gcc -fno-common關掉
08/05 01:23, 22F
文章代碼(AID): #1PWyk1z3 (C_and_CPP)