C语言 内联函数
【注:本文只討論C語言中的內聯函數,暫不談論C++,因為C++中這塊知識相對要更復雜。】
什么是內聯函數
在C語言中,如果一些函數被頻繁調用,不斷地有函數入棧,即函數棧,會造成棧空間或棧內存的大量消耗。
為了解決這個問題,特別的引入了inline修飾符,表示為內聯函數。
內聯函數是代碼被插入到調用者代碼處的函數。內聯函數通過避免被調用的開銷來提高執行效率。
采用內聯函數實質是以空間換時間的做法
舉例:
void myprintf(int a) {printf(“%d”,a); }int main() {for(i=0;i<100;i++)myprintf(i); }對于這個函數,在進行反復的打印i的過程中我們是不是要反復的調用myprintf()這個函數,進函數和出函數是需要時間的(入棧出棧),假設這個過程用時為4ms,而執行printf這個操作只需要2ms,那么在100次循環的過程中進出函數的時間比函數功能printf需要的時間還要長,這樣很影響工作效率。于是,我們就想要如何避免進出函數的過程呢?可以聲明inline這個關鍵字。
inline void myprintf(int a) {printf(“%d”,a); }int main() {for(i=0;i<100;i++)myprintf(i); }main函數中的myprintf(i);會直接替換成該函數主體,上面的代碼在編譯時實際上是這樣的:
inline void myprintf(int a) {printf(“%d”,a); }int main() {for(i=0;i<100;i++){printf(“%d”,i);} }內聯函數和宏定義區別
內聯函數看上去和宏定義非常相似。
對于上面的例子,我們可以用宏定義實現:
效果可以說與前面使用內聯的方式沒多大差別。
但宏定義在某些情況下會有問題,比如:
ans = abs1(x++); 展開是ans = ( (x++) >= 0 ? (x++) : -(x++) );
所以x++會執行2次,這可能是用戶所不希望的。
而內聯函數,與直接的函數調用區別僅在于沒有函數調用過程的消耗。保留了函數調用的特性,又提高函數的執行效率。
和宏不同的,還有內聯函數的參數類型被檢查,并且被正確地進行必要的類型轉換。
使用內聯函數注意事項
1、inline只適合函數體內代碼量少的函數使用,因為每一處內聯函數的調用都要復制代碼,如果該函數代碼量較大,將使程序的總代碼量增大,消耗更多的內存空間。
2、內聯函數本身不能是直接遞歸函數(自己內部還調用自己的函數)。因為這樣會在編譯時無窮無盡地展開。
3、如果執行函數體內代碼的時間,相比于函數調用的時間開銷較大,那么使用內聯的效率的收獲會很少。比如函數內有循環,這種情況就不考慮用內聯函數了。
4、關鍵字inline 必須與函數定義體放在一起才能使函數成為內聯,僅將inline 放在函數聲明前面不起任何作用。
inline void Foo(int x, int y); // inline 僅與函數聲明放在一起 void Foo(int x, int y) { }5、對于功能復雜,內容較多的函數,即使加上inline修飾符,也不一定能作為內聯函數,因為編譯器會判定做優化。
關于static inline
static inline的內聯函數,一般情況下不會產生函數本身的代碼,而是全部被嵌入在被調用的地方。如果不加static,則表示該函數有可能會被其他編譯單元所調用,所以一定會產生函數本身的代碼。所以加了static,一般可令可執行文件變小。—【存疑,不確定】
static inline的內聯函數,只能在本文件內調用,而沒有static則可以被其他文件調用,這與static的常用方法一致。
函數的地址被使用的時候。如通過函數指針對函數進行了間接調用。這種情況下就不得不為static inline函數生成獨立的匯編碼,否則它沒有自己的地址。
參考鳴謝:
https://blog.csdn.net/zqixiao_09/article/details/50877383
https://www.cnblogs.com/linux-bfbdxj520/p/11405474.html
https://www.jb51.net/article/41520.htm
https://blog.csdn.net/chuqierliang/article/details/48053417
https://blog.csdn.net/weixin_33895657/article/details/92037511
https://blog.csdn.net/qq_33757398/article/details/81390151
https://blog.csdn.net/weixin_30706507/article/details/96192546
總結
- 上一篇: STM32 map文件解析
- 下一篇: C语言 void和void *(无类型指