C++入門教程之內聯函數與extern?"C"詳解
一. 內聯函數
1.概念及分析
以inline修飾的函數叫做內聯函數,編譯時C++編譯器會在調用內聯函數的地方展開,沒有函數調用建立棧幀的開銷,內聯函數提升程序運行的效率。
int Add(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
int ret= Add(1, 2);
return 0;
}在我們之前使用的函數中,編譯時會建立棧幀,進而去調用


而正如上面說的那樣,內聯函數編譯時C++編譯器會在調用內聯函數的地方展開,沒有函數調用建立棧幀的開銷。我們可以用inline修飾后來看一下
查看方式:
1. 在release模式下,查看編譯器生成的匯編代碼中是否存在call Add
2. 在debug模式下,需要對編譯器進行設置,否則不會展開,因為debug模式下,編譯器默認不會對代碼進行優(yōu)化
而由于我使用的是vs2022,release模式下的匯編代碼太過簡略,我在這里就只采用debug的模式來查看。



如此設置,便能進行查看

可以看到,與普通的函數不同,內聯函數的確是在調用的地方展開。
2.特性
1. inline是一種以空間換時間的做法,如果編譯器將函數當成內聯函數處理,在編譯階段,會用函數體替換函數調用,缺陷:可能會使目標文件變大,優(yōu)勢:少了調用開銷,提高程序運行效率。
2. inline對于編譯器而言只是一個建議,不同編譯器關于inline實現機制可能不同,一般建議:將函數規(guī)模較小(即函數不是很長,具體沒有準確的說法,取決于編譯器內部實現)、不是遞歸、且頻繁調用的函數采用inline修飾,否則編譯器會忽略inline特性。
3. inline不建議聲明和定義分離,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址了,鏈接就會找不到。
3.宏
其實,在c語言中,我們使用宏也能產生類似的效果
#define ADD(x,y) ((x)+(y))
int main()
{
int ret = ADD(1, 2);
printf("%d", ret);
return 0;
}
但宏在實質上已經不是函數了,而是將ADD(x,y)作為標識符來宏定義為字符串((x)+(y))
而宏也有其優(yōu)缺點
優(yōu)點:
1.增強代碼的復用性。
2.提高性能。
缺點:
1.不方便調試宏。(因為預編譯階段進行了替換)
2.導致代碼可讀性差,可維護性差,容易誤用。
3.沒有類型安全的檢查 。
而C++中,除開短小函數使用內聯函數來替代宏,常量定義時也可以使用const、enum
二. extern “C”
由于C++是在C的基礎上提供了更多的語法和特性,所以我們能不能在C++的程序中使用C靜態(tài)庫中的函數或者在C的程序中使用C++靜態(tài)庫中的函數呢?
實際上這種想法是可行的,但是我們需要進行一些處理,這也就要使用到extern "C"
1.C++程序
依舊是以vs2022為例,我們首先需要創(chuàng)建一個靜態(tài)庫


之后我們要在靜態(tài)庫里寫一些c的函數

之后

這樣,lib文件就會在Debug中生成

C的靜態(tài)庫就處理完成了
我們再看到C++的程序
在使用C靜態(tài)庫中函數前,我們首先要包含頭文件。與以往不同,我們需要通過文件的路徑去尋找頭文件(Add.h)


通過對兩個文件的路徑進行分析,我們可以如此來引用頭文件
#include"../DS/add.h"
其中,..代表的是前往上一層目錄
然后,我們可以使用Add函數
#include<iostream>
using namespace std;
#include"../Slist/sList.h"
int main()
{
cout << Add(1, 2) << endl;
return 0;
}
當我們運行時,會出現以上的問題,這是因為我們還沒有去鏈接靜態(tài)庫

我們需要在上述位置將靜態(tài)庫中的Debug文件夾的路徑添加上

并在上述位置加入所引用的頭文件
如此,若是在C++項目中引用C++靜態(tài)庫或是在C項目中引用C靜態(tài)庫,以上操作便能完成
而為了區(qū)別兩種語言,C++的函數會被修飾,而C不會
因此我們就要使用extern "C"來表明頭文件中的函數是用C編寫的
extern "C"
{
#include"../DS/add.h"
}如此,便完成了全部的操作

2.C程序
那么當我們反過來呢?
首先我們現將上述的文件中的.c改為.cpp,.cpp改為.c 并分別做一下調整
注意:由于C不認識C++的語法,我們C++靜態(tài)庫中的函數要遵循C的語法


我們應該對靜態(tài)庫中的頭文件進行修飾。
但由于C語言中并沒有extern "C",所以我們不能直接將函數放在其中,而是需要進行條件編譯,使得C調用時不需要extern "C",C++調用時需要。
這里我們提供兩種方法
#ifdef __cplusplus
extern "C"
{
#endif
int Add(int a,int b);
#ifdef __cplusplus
}
#endif#ifdef __cplusplus #define EXTRERN_C extern "C" #else #define EXTRERN_C #endif EXTRERN_C int Add(int a,int b);
之后,別忘了重新生成一下解決方案,這樣就能實現C程序調用C++靜態(tài)庫了

總結
到此這篇關于C++入門教程之內聯函數與extern "C"詳解的文章就介紹到這了,更多相關C++內聯函數與extern "C"內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++中的多態(tài)與多重繼承實現與Java的區(qū)別
這篇文章主要介紹了C++中的多態(tài)與多重繼承實現與Java的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03

