C language 筆記: static inline function === 最近在看Coding的時候,發現了一個function的修飾用法。 ```Clike= static inline void func(); ``` 這讓我有點疑問,到底什麼是static inline。後來我在PTT的C_CPP版找到討論。 :::info 1. inline:看得到此函式的一律用inline(編譯器許可的話),看不到者不能用該函式 函式無對應的位址可供呼叫 除非該函式另外有同名的非inline版本 2. extern inline: 看得到此函式的一律用inline(編譯器許可的話),看不到者可用函式呼叫。 有對應的位址 3. static inline我就不懂了。 節錄自[PTT C_and_CPP](https://www.ptt.cc/man/C_and_CPP/DB9B/DE17/D8D6/M.1466018021.A.9B5.html) ::: :::info EdisonX的推文: 以 C 而言,global func. 加上 static 修飾,代表只能在該檔案被呼叫, 如static void func()放在 a.c,就不能在 b.c 呼叫 func(); 若不加 static 時,即使 a.h上void func();之宣告, b.c 仍可事先用extern void fun()宣告後,調用在 a.c 裡的 func()合在一起看,static inline void func(); 代表這個函式只能在某個特定檔案裡面被呼叫,而且在此檔案裡會建議編譯器直接展開,並沒衝突。(真正衝突的是extern和static)。 若以 c++ 來講,放在 class 裡面的話又是另一個故事了... ::: :::info CoNsTaR的推文: 沒加 static 別人可以自己用 extern。宣告inline的意義是告訴使用者 “定義和宣告合併”。 隱含意義是 “只會有這個實作版本” 因為實作和宣告寫在一起了 至於把程式片段取代函式呼叫 那只是編譯器自己的優inline 沒有成功與否啊 它只是用來提供資訊的關鍵字而已 對了GNU的 inline效果和standard 不一樣。但是兩者對 inline 的定義卻是相同的。兩個都拿來看看應該可以找出 inline 的本質。 ::: ### 於是乎,我做了以下幾個實驗。第一個是正常版本,並沒有用這些修飾詞的程式碼。 main.c ```Clike= #include test.h int main(){ func(); return 0; } ``` test.h ```Clike= #ifndef _TEST_H_ #define _TEST_H_ #include <stdio.h> void func(); #endif ``` test.c ```Clike= #include "test.h" void func(){ printf("test1\n"); } ``` * compile and run ``` gcc test.c main.c -o main -Wall ./main test1 ``` ### 第二個是版本,使用了extern,將function從.c檔案抽出來使用。 main.c ```Clike= #include test.h extern void func(); int main(){ func(); return 0; } ``` test.h ```Clike= #ifndef _TEST_H_ #define _TEST_H_ #include <stdio.h> #endif ``` test.c ```Clike= #include "test.h" void func(){ printf("test1\n"); } ``` * compile and run ``` gcc test.c main.c -o main -Wall ./main test1 ``` 這個例子中,我們可以看到,即使沒有宣告在header的實作,依然可以透過extern呼叫。但我們有時候想要隱藏實作,並不想將所有實作開放給其他人使用,該怎麼處理。於是來到我們的第三的版本。 ### 第三個是版本,使用了static修飾function。 main.c ```Clike= #include test.h extern void func(); int main(){ func(); return 0; } ``` test.h ```Clike= #ifndef _TEST_H_ #define _TEST_H_ #include <stdio.h> #endif ``` test.c ```Clike= #include "test.h" void func(){ printf("test1\n"); } ``` * compile and run ``` gcc test.c main.c -o main -Wall ``` 會出現以下錯誤訊息,告訴你func並未是未定義參考。 ``` test.c:3:13: warning: ‘func’ defined but not used [-Wunused-function] 3 | static void func(){ | ^~~~ /usr/bin/ld: /tmp/ccclIlr2.o: in function `main': main.c:(.text+0xe): undefined reference to `func' collect2: error: ld returned 1 exit status ``` ### 若是將function帶有inline修飾詞,就會變成第四個是版本: main.c ```Clike= #include test.h int main(){ func1(); return 0; } ``` test.h ```Clike= #ifndef _TEST_H_ #define _TEST_H_ #include <stdio.h> void func1(); #endif ``` test.c ```Clike= #include "test.h" static inline void func(){ printf("test1\n"); } void func1(){ func(); } ``` * compile and run ``` gcc test.c main.c -o main -Wall ./main test1 ``` ### 結論,我們可以透過static保護實作,不被extern引用。若將static inline合在一起,表示宣告與實作合二為一