溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++語(yǔ)言常見(jiàn)函數(shù)調(diào)用約定有哪些

發(fā)布時(shí)間:2021-10-21 14:04:56 來(lái)源:億速云 閱讀:160 作者:小新 欄目:編程語(yǔ)言

這篇文章將為大家詳細(xì)講解有關(guān)C++語(yǔ)言常見(jiàn)函數(shù)調(diào)用約定有哪些,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

一、C++語(yǔ)言函數(shù)調(diào)用約定簡(jiǎn)介

C /C++開(kāi)發(fā)中,程序編譯沒(méi)有問(wèn)題,但鏈接的時(shí)候報(bào)告函數(shù)不存在,或程序編譯和鏈接都沒(méi)有錯(cuò)誤,但只要調(diào)用庫(kù)中的函數(shù)就會(huì)出現(xiàn)堆棧異常等現(xiàn)象。上述現(xiàn)象出現(xiàn)在C和C++的代碼混合使用的情況下或在C++程序中使用第三方庫(kù)(非C++語(yǔ)言開(kāi)發(fā))的情況下,原因是函數(shù)調(diào)用約定(Calling Convention)和函數(shù)名修飾(Decorated Name)規(guī)則導(dǎo)致的。函數(shù)調(diào)用約定決定函數(shù)參數(shù)入棧的順序,以及由調(diào)用者函數(shù)還是被調(diào)用函數(shù)負(fù)責(zé)清除棧中的參數(shù)等問(wèn)題,而函數(shù)名修飾規(guī)則決定編譯器使用何種名字修飾方式來(lái)區(qū)分不同的函數(shù),如果函數(shù)之間的調(diào)用約定不匹配或者名字修飾不匹配就會(huì)產(chǎn)生以上的問(wèn)題。
C++語(yǔ)言中的函數(shù)調(diào)用約定主要針對(duì)三個(gè)問(wèn)題:
A、函數(shù)參數(shù)的入棧順序
B、清理?xiàng)5闹黧w(負(fù)責(zé)清理?xiàng)5闹黧w:函數(shù)自身還是調(diào)用函數(shù)者)
C、函數(shù)名稱重整
調(diào)用約定主要是指函數(shù)被調(diào)用的方式,C++語(yǔ)言的函數(shù)調(diào)用約定主要有stdcall,fastcall,pascal,cdecl,thiscall等約定。
在C++中,為了允許操作符重載和函數(shù)重載,C++編譯器通常按照某種規(guī)則改寫(xiě)每一個(gè)入口點(diǎn)的符號(hào)名,以便允許同一個(gè)名字(具有不同的參數(shù)類型或者是不同的作用域)有多個(gè)用法,而不會(huì)打破現(xiàn)有的基于C的鏈接器。這項(xiàng)技術(shù)通常被稱為名稱改編(Name Mangling)或者名稱修飾(Name Decoration)。C++編譯器廠商通常選擇自己的名稱修飾方案。

二、C++語(yǔ)言常見(jiàn)函數(shù)調(diào)用約定

1、__stdcall

__stdcall是StandardCall的縮寫(xiě),是C++的標(biāo)準(zhǔn)調(diào)用方式。__stdcall調(diào)用約定的規(guī)則如下:
A、所有參數(shù)從右到左依次入棧,如果是調(diào)用類成員的話,最后一個(gè)入棧的是this指針。
B、被調(diào)用函數(shù)自動(dòng)清理堆棧,返回值在EAX。
C、函數(shù)修飾名約定:VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。

2、__cdecl

__cdecl是C DECLaration的縮寫(xiě)(declaration,聲明),表示C語(yǔ)言默認(rèn)的函數(shù)調(diào)用方法。__cdecl調(diào)用約定規(guī)則如下:
A、所有參數(shù)從右到左依次入棧
B、所有參數(shù)由調(diào)用者清除,稱為手動(dòng)清棧。返回值在EAX中
C、函數(shù)修飾名約定:VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴 
由于由調(diào)用者清理?xiàng)?,所以允許可變參數(shù)函數(shù)存在,如int sprintf(char buffer,const char format,...)。

3、__fastcall

__fastcall是快速調(diào)用約定,通過(guò)寄存器來(lái)傳送參數(shù)。__fastcall調(diào)用約定的規(guī)則如下:
    A、用ECX和EDX傳送前兩個(gè)雙字(DWORD)或更小的參數(shù),剩下的參數(shù)仍舊自右向左壓棧傳送 
    B、被調(diào)用函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧 ,返回值在EAX中
    C、函數(shù)修飾名約定:VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上"@"前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù) 。

4、thiscall

thiscall是唯一一個(gè)不能明確指明的函數(shù)修飾符,thiscall只能用于C++類成員函數(shù)的調(diào)用,同時(shí)thiscall也是C++成員函數(shù)缺省的調(diào)用約定。由于成員函數(shù)調(diào)用還有一個(gè)this指針,因此必須特殊處理。
thiscall調(diào)用約定如下:
A、采用桟傳遞參數(shù),參數(shù)從右向左入棧。如果參數(shù)個(gè)數(shù)確定,this指針通過(guò)ECX傳遞給被調(diào)用者;如果參數(shù)個(gè)數(shù)不確定,this指針在所有參數(shù)壓棧后被壓入堆棧。
B、對(duì)參數(shù)個(gè)數(shù)不定的,調(diào)用者清理堆棧,否則由被調(diào)函數(shù)清理堆棧
thiscall 不是關(guān)鍵字,程序員不能使用。

5、__pascal

__pascal 語(yǔ)言的調(diào)用約定,跟 __stdcall 一樣,參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在EAX中。VC 中已經(jīng)廢棄,建議使用 stdcall 代替。

關(guān)于“C++語(yǔ)言常見(jiàn)函數(shù)調(diào)用約定有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI