gcc之inline函式探究
1、引子:行內函數(以下稱為inline函式)的行為類似於巨集,但是會像函式一樣進行引數的靜態型別檢查。因此gcc中很多地方傾向於使用inline函式來替代巨集。但是inline函式在gcc中應該如何使用呢?函式被內聯之後究竟有哪些改變呢?
#include "stdio.h"
//inline int func(int a) __attribute__((always_inline)); // func有,內聯成功puts
//inline int func(int a); // func有,未內聯
//int func(int a) __attribute__((noinline)); // func有,未內聯
//static inline int func(int a) __attribute__((always_inline)); // func無,內聯成功puts
//static inline int func(int a); // func有,未內聯
//static int func(int a) __attribute__((noinline)); // func有,未內聯
//extern inline int func(int a) __attribute__((always_inline)); // func有,未內聯
//extern inline int func(int a); // func有,未內聯
//extern int func(int a) __attribute__((noinline)); // func有,未內聯
int func(int a)
{
a += 5;
printf("inline test, a = %d\n", a);
}
int main(void)
{
func(5);
func(6);
func(7);
return 0;
}
2、測試方法:
測試程式碼如上,非常簡單的一個函式func,func在主程式中被呼叫3次。我們分別使用上面三組、每組三個的宣告方式來對func函式進行宣告。然後使用gcc inline.c -o xx 來進行編譯連結,生成可執行檔案xx,然後用objdump xx -d > xx.txt來對剛才生成的可執行程式進行反彙編,得到對應的彙編程式碼。這裡的xx在每種宣告方式下不同,我採用組號+組內編號的形式來命名,如第一種宣告方式xx為11,而最後一種宣告方式中xx為33。
測試後檢視反彙編程式碼xx.txt,重點關注兩個問題:
2.1、func有無被內聯處理?
2.2、func函式在最終的可執行程式中有沒有生成獨立程式碼段
3、結果分析:
3.1、實際的測試結果如9種宣告之後標註的,即只有11和21這兩種下func被內聯處理,其他情況下都未內聯。這是__attribute__((always_inline))產生的影響。比較有趣的是31也未被內聯,儘管使用了強制內聯,但是在extern inline下還是不進行內聯處理,這也是跟網上查到的一些資料不符的地方。
3.2、21中func未生成獨立程式碼段,而其他均有生成。這個很好理解,因為static宣告的函式只會被該文字內引用而不會被外部引用,而inline之後該文字內所有對func的引用都被內聯了,因此func沒有必要再生成獨立的程式碼段了。(程式中func本身不是遞迴函式,而且func未被賦值給某一函式指標)
4、反彙編程式碼很長很多,這裡只貼出兩組來。一是11,二是12。因為這兩組可以代表其他的情況了。而且只貼出func和main兩個函式相關的程式碼段:
-----------11.txt片段--------------------
080483e4 <func>:
80483e4: 55 push %ebp
80483e5: 89 e5 mov %esp,%ebp
80483e7: 83 ec 18 sub $0x18,%esp
80483ea: 83 45 08 05 addl $0x5,0x8(%ebp)
80483ee: b8 40 85 04 08 mov $0x8048540,%eax
80483f3: 8b 55 08 mov 0x8(%ebp),%edx
80483f6: 89 54 24 04 mov %edx,0x4(%esp)
80483fa: 89 04 24 mov %eax,(%esp)
80483fd: e8 1a ff ff ff call 804831c <[email protected]>
8048402: c9 leave
8048403: c3 ret
08048404 <main>:
8048404: 55 push %ebp
8048405: 89 e5 mov %esp,%ebp
8048407: 83 e4 f0 and $0xfffffff0,%esp
804840a: 83 ec 20 sub $0x20,%esp
804840d: c7 44 24 1c 05 00 00 movl $0x5,0x1c(%esp)
8048414: 00
8048415: 83 44 24 1c 05 addl $0x5,0x1c(%esp)
804841a: b8 40 85 04 08 mov $0x8048540,%eax
804841f: 8b 54 24 1c mov 0x1c(%esp),%edx
8048423: 89 54 24 04 mov %edx,0x4(%esp)
8048427: 89 04 24 mov %eax,(%esp)
804842a: e8 ed fe ff ff call 804831c <[email protected]>
804842f: c7 44 24 18 06 00 00 movl $0x6,0x18(%esp)
8048436: 00
8048437: 83 44 24 18 05 addl $0x5,0x18(%esp)
804843c: b8 40 85 04 08 mov $0x8048540,%eax
8048441: 8b 54 24 18 mov 0x18(%esp),%edx
8048445: 89 54 24 04 mov %edx,0x4(%esp)
8048449: 89 04 24 mov %eax,(%esp)
804844c: e8 cb fe ff ff call 804831c <[email protected]>
8048451: c7 44 24 14 07 00 00 movl $0x7,0x14(%esp)
8048458: 00
8048459: 83 44 24 14 05 addl $0x5,0x14(%esp)
804845e: b8 40 85 04 08 mov $0x8048540,%eax
8048463: 8b 54 24 14 mov 0x14(%esp),%edx
8048467: 89 54 24 04 mov %edx,0x4(%esp)
804846b: 89 04 24 mov %eax,(%esp)
804846e: e8 a9 fe ff ff call 804831c <[email protected]>
8048473: b8 00 00 00 00 mov $0x0,%eax
8048478: c9 leave
8048479: c3 ret
804847a: 90 nop
804847b: 90 nop
804847c: 90 nop
804847d: 90 nop
804847e: 90 nop
804847f: 90 nop
----------12.txt片段----------------------
080483e4 <func>:
80483e4: 55 push %ebp
80483e5: 89 e5 mov %esp,%ebp
80483e7: 83 ec 18 sub $0x18,%esp
80483ea: 83 45 08 05 addl $0x5,0x8(%ebp)
80483ee: b8 00 85 04 08 mov $0x8048500,%eax
80483f3: 8b 55 08 mov 0x8(%ebp),%edx
80483f6: 89 54 24 04 mov %edx,0x4(%esp)
80483fa: 89 04 24 mov %eax,(%esp)
80483fd: e8 1a ff ff ff call 804831c <[email protected]>
8048402: c9 leave
8048403: c3 ret
08048404 <main>:
8048404: 55 push %ebp
8048405: 89 e5 mov %esp,%ebp
8048407: 83 e4 f0 and $0xfffffff0,%esp
804840a: 83 ec 10 sub $0x10,%esp
804840d: c7 04 24 05 00 00 00 movl $0x5,(%esp)
8048414: e8 cb ff ff ff call 80483e4 <func>
8048419: c7 04 24 06 00 00 00 movl $0x6,(%esp)
8048420: e8 bf ff ff ff call 80483e4 <func>
8048425: c7 04 24 07 00 00 00 movl $0x7,(%esp)
804842c: e8 b3 ff ff ff call 80483e4 <func>
8048431: b8 00 00 00 00 mov $0x0,%eax
8048436: c9 leave
8048437: c3 ret
8048438: 90 nop
8048439: 90 nop
804843a: 90 nop
804843b: 90 nop
804843c: 90 nop
804843d: 90 nop
804843e: 90 nop
804843f: 90 nop
相關推薦
gcc之inline函式探究
1、引子:行內函數(以下稱為inline函式)的行為類似於巨集,但是會像函式一樣進行引數的靜態型別檢查。因此gcc中很多地方傾向於使用inline函式來替代巨集。但是inline函式在gcc中應該如何使用呢?函式被內聯之後究竟有哪些改變呢? #include "stdio.
C++之inline函式使用總結
一、C++為什麼引入inline函式? 主要目的:用它代替C語言中表達式形式的巨集定義來解決程式中函式呼叫的效率問題。C語言中的巨集定義,它使用前處理器實現,沒有了引數壓棧、程式碼生成等一系列得到操作,因此效率很高。 但缺點如下: 前處理器符號表中的簡單替換,不能進行引數有
Effective C++筆記之十五:inline函式的裡裡外外
1.inline函式簡介 inline函式是由inline關鍵字來定義,引入inline函式的主要原因是用它替代C中複雜易錯不易維護的巨集函式。 2.編譯器對inline函式的處理辦法 inline對於編譯器而言,在編譯階段完成對inline函式的處理。將呼叫動作替換為函式的本體。但是它只是一種
小問題大思考之C++裡的inline函式
inline,一個神奇的關鍵字。有了它,你同時就可以獲取函式和巨集的優點。inline定義的函式,比起沒有inline的函式來說,沒有執行函式呼叫所帶來的負擔(對此可參見《C++程式的記憶體佈局》),因此它是高效率的;比起巨集來,它具有函式的可預期行為和引數型別檢驗。巨集的
c++筆記之CArray函式
謹以此文獻給因為我菜雞同時裝了VS2013和2017導致vs各種衝突,以至於只能重灌系統的新電腦!哭泣.... CArray屬於MFC,是一個數組模板類。MFC的陣列類支援的陣列類似於常規陣列,可以存放任何資料型別。常規陣列在使用前必須將其定義成能夠容納所有可能需要的元素,即先確定大小,而M
gcc與g++的探究
Windows中我們常用vs來編譯編寫好的C和C++程式碼;vs把編輯器,編譯器和偵錯程式等工具都整合在這一款工具中,在Linux下我們能用什麼工具來編譯所編寫好的程式碼呢,其實Linux下這樣的工具有很多,但我們只介紹兩款常用的工具,它們分別是gcc和g++. 工具用法介紹 gcc和g++的用
Shell之function函式的定義及呼叫
文章目錄 `function`函式的定義及呼叫 `function`函式的定義 `function`函式的呼叫【位置傳參】 函式使用return返回值【位置傳參】 函式的呼叫【陣列傳參】
Excel操作之VLOOKUP函式
1、作用 VLOOKUP函式是Excel中的一個縱向查詢函式,它與LOOKUP函式和HLOOKUP函式屬於一類函式,在工作中都有廣泛應用,例如可以用來核對資料,多個表格之間快速匯入資料等函式功能。功能是按列查詢,最終返回該列所需查詢列序所對應的值;與之對應的HLOOKUP是按行查詢的。 2、語法規則
golang教程之一類函式
文章目錄 一類函式 什麼是一類函式? 匿名函式 使用者定義的函式型別 高階函式 從其他函式返回函式 閉包 一類函式的使用 一類函式 原文:https://golan
Function 之 Read_Text 函式的使用方法
在SAP系統中,有時候會有大段文字內容需要儲存.例如:銷售發貨(VL03N),在單據的概覽中 ,有一個[文字]項,在此處可以填寫單據的大段文字描述,那麼該內容儲存在哪裡呢?第一反應是找對應表的欄位,那麼你可能要失望了。在SAP系統中,可以供我們使用的資料庫欄位最大長度是255個文字字元(注:此處可能
地理位置geo處理之mysql函式
目前越來越多的業務都會基於LBS,附近的人,外賣位置,附近商家等等,現就討論離我最近這一業務場景的解決方案。 原文:https://www.jianshu.com/p/455d0468f6d4 目前已知解決方案有: mysql 自定義函式計算
Python函式之系統函式的呼叫
全部測試程式碼 #!/usr/bin/evn python3 #_*_conding:utf-8 _*_ #系統內建函式 #1.abs():檢視絕對值,如果傳入的引數不對,會報TypeError print('-100的絕對值--',abs(-100)) #2.max():檢
學渣學python之map函式
map()函式是Python內建的高階函式,它接收一個函式f和一個list,並把函式f作用在list的每個元素上。從而得到一個f處理過的新的list返回。下面舉個栗子: 1. 例1 list [1, 2, 3, 4, 5, 6, 7] 我們要得到list的每個元素都平方後的,新的li
pytho系統學習:第二週之字串函式練習
# Author : Sunny# 雙下劃線的函式基本沒用# 定義字串name = 'i am sunny!'# 首字母大寫函式:capitalizeprint('-->capitalize:', name.capitalize())# 判斷結尾函式:endswithprint('-->endsw
matlab之sortrows()函式
sortrows()函式的格式: sortrows(A,column) A是一個矩陣,如果沒有第二個引數column,則預設按照第一列升序排列,如果遇到重複數字,則按照第二列升序排列,依次類推。。。 如果存在第二個引數column,則按照指定的列排序,當指定的列有重複元素的時候,則重複元素所在的行保持原
Promise原始碼閱讀之建構函式+then過程
前言 Promise是非同步程式設計的一種方案,ES6規範中將其寫入規範標準中,統一了用法。 考慮到瀏覽器的相容性,Vue專案中使用promise,就具體閱讀promise原始碼,看看內部的具體實現。 具體分析 通過具體例項來閱讀promise原始碼的實現,例項如下: new
C# socket 程式設計之 accept() 函式返回值解析
accept() 函式會返回一個新的套接字,這個新的套接字在伺服器端與客戶端進行通訊。 伺服器端的繫結監聽是一個套接字,與客戶端通訊的是另一個套接字(accept函式返回的套接字,注意這裡不是返回客戶端的套接字,返回的套接字是新建立在伺服器上的,與客戶端收發訊息用的) 下面這段程式碼,是
KMP演算法之next函式解釋(大量的反證法 和數學歸納法來襲)
先放get_nextval()函式的程式碼 void get_nextval(const char str[],int *net) { net[0]=-1; int j=0,k=-1,len; len=strlen(str); while(j<len)
STL之查詢函式
STL之二分查詢 (Binary search in STL) Section I 正確區分不同的查詢演算法count,find,binary_search,lower_bound,upper_bound,equal_range 本文是對Effective STL第45條的一個總結,闡述了各種
HashMap原始碼之建構函式--JDK1.8
建構函式 變數解釋 capacity,表示的是hashmap中桶的數量,初始化容量initCapacity為16,第一次擴容會擴到64,之後每次擴容都是之前容量的2倍,所以容量每次都是2的次冪 loadFactor,負載因子,衡量hashmap一個滿的程度,初始預設為0.75 thresho