Re: [問題] static inline的使用時機

作者: EdisonX (卡卡獸)   2016-06-16 00:58:16
原文後面提到的東西愈來愈多,此篇一點一點慢慢討論,
沒 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, 不讓人亂搞
~~~~~~
以上,故事有點長,若敘述有誤,請不吝指正。
謝謝收聽。
作者: wtchen (沒有存在感的人)   2016-06-16 01:52:00
感謝。不知VS對於static inline的function是否會省去產生assembly code的步驟?(compiler允許inline時)
作者: EdisonX (卡卡獸)   2016-06-16 01:58:00
會省,本質上 inline 是展開 , static 就是 scope 。
作者: suhorng ( )   2016-06-18 13:34:00
記得 static inline 不是都可以直接放 .h 檔裡XD看得到定義才能 inline, 想要大家 #include 又不能multiple definition 就放 static 嗎?
作者: lantw44 (#######################)   2016-06-19 01:28:00
在 C 放 .h 的應該通常都是 static inline?只有寫 inline 的話,如果編譯器不打算 inline,應該會變成 undefined reference 吧。
作者: EdisonX (卡卡獸)   2016-06-19 02:09:00
@lantw44 , 我手邊的 vs .c 連 inline 都不支援了。
作者: wtchen (沒有存在感的人)   2016-06-19 02:17:00
VS的.c有鳥到連inline都不支援喔?
作者: EdisonX (卡卡獸)   2016-06-19 06:31:00
vs2010 , 可試試。不過話說 vs 對純 c 的支援一向不好,對新標準的進度也慢
作者: lantw44 (#######################)   2016-06-19 11:18:00
聽說 VS 一直都不太在意 C 標準
作者: uranusjr (←這人是超級笨蛋)   2016-06-20 02:21:00
微軟只關心 C++ 啊, C 編譯器基本上只是順便做做
作者: wtchen (沒有存在感的人)   2016-06-20 15:55:00
不過VS主要就是開發application的,寫Windows OS應該不會用VS吧?不像gcc就是做來開發kernel的(好奇MS用啥開發Win OS...)
作者: suhorng ( )   2016-06-22 01:38:00
咦~ 為什麼 Visual C 不能拿來開發 OS
作者: wtchen (沒有存在感的人)   2016-06-22 15:57:00
我只是猜啦沒有這樣說,不知道有沒有人知道MS怎麼開發OS
作者: Caesar08 (Caesar)   2016-06-22 20:39:00
在VC上,C++進展很快,已經支援部分C++17了。不過C就...
作者: wtchen (沒有存在感的人)   2016-06-23 02:06:00
MS是用C還是C++寫OS阿?
作者: Schottky (順風相送)   2016-06-23 16:57:00
https://technet.microsoft.com/library/cc767881.aspx照這網頁的說法,大部份是用 C 和 C++ 寫的,少部份組語而且雖然很少用到,VS 有包含 kernel remote debugger

Links booklink

Contact Us: admin [ a t ] ucptt.com