深入理解內聯函數(C語言)

目錄

  • 1.什么是內聯函數
  • 2.內聯函數與宏
  • 3.編譯器對內聯函數的處理
  • 4.參考文獻

1.什么是內聯函數

很多人都會知道,可以將比較小的函數寫成內聯函數的形式,這樣會節省函數調用的開銷,具體是什么樣的開銷呢?
一個函數在執行過程中,如果需要調用其他函數,則一般會執行下面的過程。

  1. 保存當前函數現場
  2. 跳到調用函數執行
  3. 恢復當前函數現場
  4. 繼續執行當前函數

一個C語言程序,在main()函數中對某些數據進行處理,運算結果暫時保存在R0寄存器中。接著調用另一個函數call_fun(),調用結束后,返回main()函數繼續執行。如果我們在call_fun()函數中要用到R0寄存器,就會改變R0中的值,當我們返回main()中繼續執行程序的時候,就會出現錯誤的計算。

處理辦法很簡單,就是在跳到call_fun()之前,先將R0中的值保存到對戰中,調用結束后,再將其值取出來,這樣就可以順利地執行main()函數了。這就是所謂的現場保存和恢復。

對于一般的函數調用,當然沒有什么問題,但如果需要調用的函數本來就很小(指令和數據都不多),這個時候如果頻繁地調用,就會出現頻繁地保存現場,恢復現場,降低了程序的執行效率,這個時候就可以將call_fun()改寫為內聯函數,簡單高效。

2.內聯函數與宏

內聯函數和宏的功能差不多,為什么不直接定義一個宏,而去定義一個內聯函數呢?二者又有什么不同呢?

與宏相比,內聯函數具有以下優勢。

  • 參數類型檢查:內聯函數具有宏的展開特性,但本質仍是函數,在編譯過程中,編譯器仍然可以對其進行參數檢查,而宏不具備此功能。
  • 便于調試:函數支持豐富的斷點調試功能,而宏定義不支持,這樣便于軟件的調試和開發。
  • 接口封裝:有些內聯函數可以用來封裝一個接口,而宏并無此特性。

3.編譯器對內聯函數的處理

眾所周知,并不是在函數前添加了inline關鍵字,程序在執行過程中就會乖乖執行內聯展開,這與開發者和計算機都有關系。

而若要得知函數是否真正進行了內聯展開,則需要深入底層,從匯編程序中得知。

尺有所短,寸有所長,內聯函數也有缺點。內聯函數會增大程序的體積,如果在一個文件中多次調用內聯函數,多次展開,則整個函數的體積就會變大,降低了代碼的執行效率。這與函數的設計初衷相悖(函數的作用之一就是提高代碼的復用性)。

編譯器在對內聯函數做展開時,除了檢測用戶定義的內聯函數是否有指針、循環、遞歸,還會在函數執行效率和函數調用開銷之間進行權衡。一般來說,從程序員角度來說,主要考慮以下因素。

  • 函數體積小。
  • 函數體內無指針賦值、遞歸、循環等語句。
  • 調用頻繁。

下面的例子,我們用一個簡單的程序實現了某個數的階乘。
在這里插入圖片描述
我們封裝了兩個函數,都含有linline關鍵字,而從編譯后的匯編程序可以看出,一個函數進行了內聯展開,而另一個可能考慮到了函數并不是很精簡,并未對其進行內聯展開。

然后將優化等級調到了1,再看看結果:
在這里插入圖片描述
可以看到,將兩個函數都進行了內聯展開。輸出結果仍然是24,保持不變。

接下來我們使用GCC編譯器提供的特性__attribute__來實現強制內聯:
在這里插入圖片描述
可以看到,此時即使關閉了優化等級,編譯器還是對兩個內聯函數進行了內聯展開。程序的運行結果也不會受影響。

此次我們采用了在線的編譯工具,感覺還不錯,喜歡的同學可以試試。
Compiler Explorer

4.參考文獻

《嵌入式C語言自我修養》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/15476.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/15476.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/15476.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

v-if 與 v-show(vue3條件渲染)

v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷毀和重建。 v-if 也是惰性的:如果在初始渲染時條件為假,則什么也不做——直到條件第一次變為真時,才會開始渲染條件塊。 相比之下&a…

Java—單例模式

什么是單例模式? 單例模式是一種軟件設計模式,它確保一個類只有一個實例,并提供一個全局訪問點來訪問該實例。在單例模式中,類自身負責創建自己的唯一實例,并且保證在整個應用程序中只能訪問到這個實例。 實現步驟&a…

IDEA通過tomcat運行注意事項

配置run--》edit configurations 以下的A B部分要保持一致 A和B的路徑要保持一致

前端vue項目遇到的問題01——那些初級問題

前端vue項目遇到的問題01——那些初級問題 1. npm install 問題1.1 依賴沖突1.1.1 詳細問題1.1.2 報錯原因1.1.3 解決問題1.1.3.1 方式1——無視沖突1.1.3.1 方式2——更換依賴版本 1.2 nodejs版本問題1.3 node版本正確的情況(audit問題)(這個…

Java鏈表簡介

在Java中使用鏈表作為一種數據結構,并將其與MySQL作為底層數據庫進行集成,涉及幾個關鍵方面,包括數據存儲、數據操作的效率、以及如何在應用層和數據庫層之間映射數據結構。下面是對這些方面的分析: ### Java中的鏈表數據結構 鏈…

HTML5新特性、JS【初識JS 、JS核心語法】--學習JavaEE的day47

day47 HTML5新特性 定義文檔類型 在文件的開頭總是會有一個標簽 語言文檔類型聲明方式html4<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">html5<!DOCTYPE html> 新增語義化標簽 理解&…

vite-plugin-vue-devtools插件

vite-plugin-vue-devtools插件旨在幫助開發者更快地理解并調試Vue應用。它通過提供全面的功能和直觀的界面&#xff0c;以圖形化的方式展示應用程序狀態&#xff0c;使開發者能夠更方便地查看和管理Vue應用的各個方面。此外&#xff0c;該插件還支持Vue3.0版本&#xff0c;并且…

【Go專家編程——內存管理——垃圾回收】

垃圾回收 所謂的垃圾就上不在需要的內存塊&#xff0c;垃圾如果不清理&#xff0c;這些內存塊就沒有辦法再次被分配使用。在不支持垃圾回收的編程語言中&#xff0c;這些垃圾內存就上泄露的內存。 1. 垃圾回收算法 常見的垃圾回收算法有3種 引用計數&#xff1a;對每個對象…

yolov10 快速使用及訓練

參考: https://docs.ultralytics.com/models/yolov10/ ultralytics其實大多數系列都能加載使用: 官方: https://github.com/THU-MIG/yolov10.git 代碼參考: https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/train-yolov10-object-…

一篇文章講透排序算法之希爾排序

希爾排序是對插入排序的優化&#xff0c;如果你不了解插入排序的話&#xff0c;可以先閱讀這篇文章&#xff1a;插入排序 目錄 1.插入排序的問題 2.希爾排序的思路 3.希爾排序的實現 4.希爾排序的優化 5.希爾排序的時間復雜度 1.插入排序的問題 如果用插入排序對一個逆序…

521源碼-免費代碼基礎學習-PHP如何運用變量教程

更多網站源碼學習教程&#xff0c;請點擊&#x1f449;-521源碼-&#x1f448;獲取最新資源 為什么要學習PHP&#xff1f;“我可以用JavaScript來實現程序編寫。”但JavaScript的能力是有限的&#xff0c;JavaScript通常運行在瀏覽器&#xff08;客戶端&#xff09;&#xff0…

go語言中for的4種循環形式總結

和其他語言不一樣&#xff0c;go語言中的循環語句只有for一種&#xff0c;但是go里面的for卻有3種不同的循環形式&#xff0c;總結如下&#xff1a; 1. 無限循環 for { //這個就是一個“死循環”&#xff0c;注意必須要有 break條件&#xff0c;否則就真成死循環了 } 2. fo…

Redis 源碼學習記錄:集合 (set)

無序集合 Redis 源碼版本&#xff1a;Redis-6.0.9&#xff0c;本篇文章無序集合的代碼均在 intset.h / intset.c 文件中。 Redis 通常使用字典結構保存用戶集合數據&#xff0c;字典鍵存儲集合元素&#xff0c;字典值為空。如果一個集合全是整數&#xff0c;則使用字典國語浪費…

PostgreSQL入門教程

PostgreSQL是一種開源的關系型數據庫管理系統&#xff0c;它具有高度的可靠性、可擴展性和性能。下面是一個簡單的PostgreSQL入門教程&#xff0c;幫助你開始使用這個強大的數據庫管理系統。 步驟1&#xff1a;安裝PostgreSQL 首先&#xff0c;你需要下載并安裝PostgreSQL。你…

2024年最全的信息安全、數據安全、網絡安全標準分享(可下載)

以上是資料簡介和目錄&#xff0c;如需下載&#xff0c;請前往星球獲取&#xff1a;https://t.zsxq.com/Gz1a0

【全網最全】2024電工杯數學建模A題成品論文+前三題完整解答matlab+py代碼等(后續會更新成品論文)

您的點贊收藏是我繼續更新的最大動力&#xff01; 一定要點擊如下的卡片鏈接&#xff0c;那是獲取資料的入口&#xff01; 【全網最全】2024電工杯數學建模A題成品論文前三題完整解答matlabpy代碼等&#xff08;后續會更新成品論文&#xff09;「首先來看看目前已有的資料&am…

Python 點云平面分割【RANSAC算法】

點云平面分割 一、介紹1.1 概念1.2 算法思路1.3 參數設置二、代碼示例三、結果示例其他參考鏈接:C++中實現點云平面分割 一、介紹 1.1 概念 點云平面分割:可以在點云數據中找到平面并計算平面模型系數,同時輸出平面點云及非平面點云。 1.2 算法思路 實現思路: 首先,采用…

Sass是什么?有哪些優缺點?

目錄 一、Sass是什么&#xff1f; 二、Sass的優缺點 三、Sass與SaaS 一、Sass是什么&#xff1f; Sass是世界上最成熟、最穩定、最強大的專業級CSS擴展語言。 Sass makes CSS fun again. Sass is an extension of CSS, adding nested rules, variables, mixins, selector in…

【C++高階(一)】繼承

目錄 一、繼承的概念 1.繼承的基本概念 2.繼承的定義和語法 3.繼承基類成員訪問方式的變化 ?編輯 4.總結 二、基類和派生類對象賦值轉換 三、繼承中的作用域 四、派生類的默認成員函數 1.派生類中的默認構造函數 2.派生類中的拷貝構造函數 3.派生類中的移動構造函數…

英語學習筆記25——Mrs. Smith‘s kitchen

Mrs. Smith’s kitchen 史密斯太太的廚房 詞匯 Vocabulary Mrs. 夫人【已婚】 復習&#xff1a;Mr. 先生 全名 / 姓    Mrs. 夫人 全名 / 丈夫的姓    Miss 小姐&#xff08;未婚&#xff09; 全名 / 姓    Ms. 女士 全名 / 姓 查看婚姻狀況&#xff0c;可以觀察…