看板 C_and_CPP 關於我們 聯絡資訊
原文後面提到的東西愈來愈多,此篇一點一點慢慢討論, 沒 k 過 spec., 沒追過 assembly code,有誤請不吝指正。 先談 inline 的特性 , 再討論 static , 用大量的程式碼做輔助說明應該會清楚些。 另由於我手邊的 vs2010 要用 inline 就得用 cpp ,故暫時先以 c++ 的方式探討。 以下說的 "DEBUG MODE" 指的是沒有任何優化參數; "RELEASE MODE" 指的是有下 -O2 優化參數。 壹、inline 的確一般的 inline function,實作和宣告會放在同一個檔案裡面,如下。 例 1.1 (correct) // mymath.h #pragma once inline int inc(int a) { return a+1; } // main.cpp #include "mymath.h" int main() { inc(1) ; return 0;} 若拆成 mymath.h / mymath.cpp 做的話,的確在 compile 時就會有語法上的錯誤 例 1.2 (error) // mymath.h #pragma once inline int inc(int v); // mymath.cpp #include "mymath.h" inline int inc(int v) { return v+1;} // main.cpp #include "mymath.h" int main() { inc(1) ; return 0;} inline 做的事情是 "建議" compiler 不要實際產生一個 function, 而是如你說的,像是用 macro 的方式在呼叫的地方做替換,但這件事是叫 "建議",而不是 "絕對"。而這個 "建議",通常在 Debug Mode 都是無效的, 這點不論 gcc 或 vs 都一樣。故在 MFC 的一些 src code 會透過 macro 進行 inline switch 作法,也就是在 Debug Mode 時,該函式不實作為 inline 函式; 在 Release Mode 時會實作為 inline 函式,所以 MFC src 會看到另一種副檔 名的 src code : XXXX.inl,讓人感覺很繞路,但會這麼做的原因是想讓 編譯速度加快,不過我沒測過時間就是。 上篇提到的的,compiler 強度可以決定要不要 inline,答案是沒錯的, 甚至我認為說不定未來 inline 關鍵字和 register 關鍵字走向一樣的結果, 在 Debug Mode 的時候基本上是完全不理會,一律用一般 function / variable 方式處理;在 Release Mode 也是忽視這二個識別字,因 user 要不要用 inline 或是 register 的建議,對 compiler 而言可能都很爛,還不如讓 compiler 自己做就好。這也是為什麼 vs release mode 下中斷點,有些變數 看不到、有些函式進不去的原因 (因都被優化掉了)。 貮、static 回到 mymath 問題,但若今天的情況是,我在實作 mymath 的所有對外 functions (像是 mysin, mycos, mytan... 等讓其他 coder 使用的), 並不打算讓其他 coder 在引入 mymath.h 時可以用到 inc 時,我的 inc 就不想放在 mymath.h 裡面,只想實作在 mymath.cpp 裡,且考慮 到 inc 較適合用 inline,情況就變如下 例 2.1 // mymath.h #pragma once double mysin(double x); double mycos(double x); // mymath.cpp #include "mymath.h" inline int inc(int v) { return v+1;} double mysin(double x){...} double mycos(double x){...} 一般 "正常使用" , 沒有人在 main.cpp 做 extern 時, Release Mode 下 inc 會被做 inline 沒錯,但若今天有人無聊,想在 main.cpp 中,hack 到 mymath.cpp 裡面的 inc 時,情況就不一樣了。 例 2.2 // main.cpp #include "mymath.h" extern int inc(int v); int main() { inc(1) ; return 0;} 這時由於 inc function 在其他檔案 extern 出來,在 mymath.cpp 裡的 inc 就不會被用 inline 內崁在程式碼裡,但 extern inline 這特性說真的,主要 還是看 compiler 有沒有能力再做 inline。為了避免我原本不想開放、要 inline 的 東西被亂搞,搞成不能變 inline,就在 mymath.cpp 裡的 inc 變成 static inline 修飾,讓其他人沒辦法用 extern 抽出來。如下。 例 2.3 // mymath.h #pragma once double mysin(double x); double mycos(double x); // mymath.cpp #include "mymath.h" static inline int inc(int v) { return v+1;} double mysin(double x){...} double mycos(double x){...} // main.cpp #include "mymath.h" extern int inc(int v); int main() { inc(1) ; return 0;} // 這裡會報 error, 不讓人亂搞 ~~~~~~ 以上,故事有點長,若敘述有誤,請不吝指正。 謝謝收聽。 -- 「自從我學了 C# , 人都變聰明 , 考試都考一百分」 「自從我學了 VB , 皮膚都變好 , 人也變漂亮了 」 「自從我學了 Java , 明顯變壯 , 個子也變高了 」 「自從我學了 C++ , 內分泌失調 , 頭都禿了... 」 < Kuso 星爺語錄 > -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.195.164.103 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1466009905.A.DAE.html
wtchen: 感謝。不知VS對於static inline的function是否會省去 06/16 01:52
wtchen: 產生assembly code的步驟?(compiler允許inline時) 06/16 01:53
EdisonX: 會省,本質上 inline 是展開 , static 就是 scope 。 06/16 01:58
suhorng: 記得 static inline 不是都可以直接放 .h 檔裡XD 06/18 13:34
沒錯, 可以, 只是 .h 放 inline 我不知道幹嘛特別加 static
suhorng: 看得到定義才能 inline, 想要大家 #include 又不能 06/18 13:35
suhorng: multiple definition 就放 static 嗎? 06/18 13:35
目前我自己用的 static inline 是放在 .c / .cpp 裡。 ※ 編輯: EdisonX (123.195.138.11), 06/18/2016 23:37:04
lantw44: 在 C 放 .h 的應該通常都是 static inline? 06/19 01:28
lantw44: 只有寫 inline 的話,如果編譯器不打算 inline, 06/19 01:29
lantw44: 應該會變成 undefined reference 吧。 06/19 01:30
EdisonX: @lantw44 , 我手邊的 vs .c 連 inline 都不支援了。 06/19 02:09
wtchen: VS的.c有鳥到連inline都不支援喔? 06/19 02:17
EdisonX: vs2010 , 可試試。 06/19 06:31
EdisonX: 不過話說 vs 對純 c 的支援一向不好,對新標準的進度也慢 06/19 06:32
lantw44: 聽說 VS 一直都不太在意 C 標準 06/19 11:18
uranusjr: 微軟只關心 C++ 啊, C 編譯器基本上只是順便做做 06/20 02:21
wtchen: 不過VS主要就是開發application的,寫Windows OS 06/20 15:55
wtchen: 應該不會用VS吧?不像gcc就是做來開發kernel的 06/20 15:56
wtchen: (好奇MS用啥開發Win OS...) 06/20 15:56
suhorng: 咦~ 為什麼 Visual C 不能拿來開發 OS 06/22 01:38
wtchen: 我只是猜啦沒有這樣說,不知道有沒有人知道MS怎麼開發OS 06/22 15:57
Caesar08: 在VC上,C++進展很快,已經支援部分C++17了。不過C就... 06/22 20:39
wtchen: MS是用C還是C++寫OS阿? 06/23 02:06
Schottky: 照這網頁的說法,大部份是用 C 和 C++ 寫的,少部份組語 06/23 16:58
Schottky: 而且雖然很少用到,VS 有包含 kernel remote debugger 06/23 17:21