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合在一起,表示宣告與實作合二為一