本篇 ShengYu 介紹 C/C++ extern 用法與範例。
以下 C/C++ extern 的用法與範例分為這幾部分介紹,
- C/C++ extern 引用外部變數
- C/C++ extern 引用外部函式
那我們開始吧!
C/C++ extern 引用外部變數
這邊介紹 C/C++ extern 引用外部變數的使用方式,這邊指的是 extern 引用外部的全域變數,這個方法使用的前提是該變數不能為 static,static 的用法之前有介紹過,假設我有 main.cpp、a.h、a.cpp、b.h、b.cpp 這幾隻檔案,在 main 函式裡呼叫 bbb 函式,bbb 函式位於 b.cpp 裡,但 bbb 函式會使用到 a.cpp 裡的全域變數 counter 的話要怎麼使用呢?
這邊 ShengYu 舉個簡單的範例,在 main.cpp 很簡單的呼叫 aaa()
函式以後,再呼叫 bbb()
函式,接下來看看這流程,1
2
3
4
5
6
7
8
9
int main() {
aaa();
printf("%d\n", bbb(5));
return 0;
}
a.h 內容如下,很簡單的只有 aaa 函式原型宣告,1
void aaa();
a.cpp 內容如下,counter 變數宣告是在 a.cpp 裡的全域變數,呼叫 aaa 函式則會增加 counter,注意的是這邊 counter 如果宣告成 static 則其它 *.cpp 則無法引用,這用途相似於 class 裡的 private 變數的概念,1
2
3
4
5int counter = 0;
void aaa() {
counter++;
}
b.h 內容如下,很簡單的只有 bbb 函式原型宣告,1
int bbb(int x);
b.cpp 內容如下,使用 extern 來標記/引用 counter 這個全域變數,所以這邊 b.cpp 實際上不會產生一個 counter 變數的實體,在編譯連結時期會引用 a.o 的 counter,1
2
3
4
5extern int counter;
int bbb(int x) {
return x + counter;
}
使用以下 g++ 指令進行編譯與連結,順序為將 a.cpp 編譯成 a.o 中繼檔,將 b.cpp 編譯成 b.o 中繼檔,將 main.cpp 編譯成 main.o 中繼檔,最後將這些中檔連結起來輸出成 a.out 執行檔,1
2
3
4g++ -c a.cpp
g++ -c b.cpp
g++ -c main.cpp
g++ -o a.out main.o a.o b.o
執行 a.out 的結果輸出如下,1
6
由上面的實驗可以了解 C/C++ extern 的用法與用途,那反過來想如果今天我的全域變數不想給別人 extern 時就可以加上 static。
延伸閱讀:C/C++ static 的 5 種用法
C/C++ extern 引用外部函式
既然 extern 有引用外部變數的方式,那麼有沒有 extern 引用外部函式呢?
結果是有的!C/C++ extern 引用外部函式跟引用外部變數用法差不多,這邊就簡單介紹一下,基本上要 extern 的函式前提是該函式不能為 static,這點跟 extern 外部變數一樣,函式前面加上 static 的用意就是希望它只能在這支原始檔裡使用,不想給別人呼叫,有點像 class 裡的 private function 的味道,所以要 extern 函式要先確定一下這件事,否則會編譯失敗,
這邊就簡單舉例一下,跟前述例子差不多,只是這次沒有 a.h 跟 b.h,而且 a.cpp 新增了 print_counter 函式來印出 counter,以下是 a.cpp 內容,1
2
3
4
5
6
7
8
9
10
11
int counter = 0;
static void print_counter(int c) {
printf("counter: %d\n", c);
}
void aaa() {
counter++;
print_counter(counter);
}
b.cpp 內容如下,跟前述例子一樣,1
2
3
4
5extern int counter;
int bbb(int x) {
return x + counter;
}
main.cpp 內容如下,可以看到在 main.cpp 裡可以使用 extern 引用 aaa 與 bbb 函式,extern 引用函式後就可以順利使用,編譯跟執行是沒有問題的!但是如果要 extern print_counter 函式的話編譯時就會連結錯誤,1
2
3
4
5
6
7
8
9
10
11
12
extern void aaa();
extern int bbb(int x);
//extern void print_counter(int c); // 連結錯誤, 因為 print_counter 是 static
int main() {
aaa();
printf("%d\n", bbb(5));
//print_counter(10); // 連結錯誤, 因為 print_counter 是 static
return 0;
}
編譯的指令如下,跟前述例子一樣,1
2
3
4g++ -c a.cpp
g++ -c b.cpp
g++ -c main.cpp
g++ -o a.out main.o a.o b.o
執行 a.out 的結果輸出如下,1
2counter: 1
6
如果嘗試在 main.cpp extern print_counter 並呼叫 print_counter 函式的話,編譯時會連結錯誤,錯誤訊息如下,1
2
3main.o: In function `main':
main.cpp:(.text+0x2a): undefined reference to `print_counter(int)'
collect2: error: ld returned 1 exit status
延伸閱讀:C/C++ static 的 5 種用法
C/C++ extern 還有另一種用法是 extern "C"
,下次有機會再給大家介紹。
以上就是 C/C++ extern 用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!
其它參考
https://medium.com/@alan81920/c-c-%E4%B8%AD%E7%9A%84-static-extern-%E7%9A%84%E8%AE%8A%E6%95%B8-9b42d000688f
https://docs.microsoft.com/zh-tw/cpp/cpp/extern-cpp?view=msvc-170
https://mitblog.pixnet.net/blog/post/37137361
其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ static 的 5 種用法