C C 呼叫約定

2021-07-24 13:55:31 字數 2714 閱讀 6482

c/c++函式呼叫約定

在程式設計中,乙個函式完整的執行需要經過編譯鏈結等多個過程,而在每個過程中編譯器都需要為程式提供不同的服務,那麼乙個函式的呼叫執行到底需要幾個過程呢?下面我們先通過乙個函式棧幀的建立看看。

#define

_crt_secure_no_warnings 1

#include

#include

int add(int

left, int

right)

return

left + right;

int main()

int a, b;

int ret = 0;

scanf("%d%d", &a, &b);

ret = add(a, b);

system("system");

return 0;

在這個程式中,我們來通過add()函式的內部彙編**來看看整個函式的執行過程:

下面我們用語言描述一下整個過程:

1. 為函式開闢空間

2. 初始化已開闢空間

3. 把函式

引數壓棧

4. 執行函式

5. 處理函式返回值

6. 對於第

3步中壓棧的那些暫存器,恢復它們原來的值

7. 根據不同的呼叫約定,清除第

1步中壓棧的引數,然後返回,或者先返回然後清除。

可以看到第

6步是第

3步的逆操作,而第

7步是第1,

2步的逆操作,

在第3步中對函式的引數進行壓棧,那麼當引數個數多於乙個時,編譯器會按照什麼順序把引數壓入棧的?而在第6、

7步中又是怎麼把堆疊恢復原裝?這就引出了我們今天要討論的題目——呼叫約定。

首先我們先來看看常用的幾種呼叫約定:

在c語言中有:

__cdecl

、__stdcall

、__fastcall

、naked

、__pascal

在c++中有:

__cdecl

、__stdcall

、__fastcall

、naked

、__pascal

、_thiscall vc

中預設呼叫是

__cdecl 

方式,windows api 

使用__stdcall 

呼叫方式,在

dll 

匯出函式中,為了跟

windows api 

保持一致,建議使用

__stdcall 

方式。在vc中,可以設定預設的呼叫約定,設定路徑為:project 

àproperties 

àconfiguration properties

àc/c++ 

àadvanced 

àcall conversion

下面我們就來詳細介紹一下這六種呼叫約定:

1

、__cdecl

__cdecl呼叫約定又稱為 c 呼叫約定,是 c/c++ 語言預設的呼叫約定。引數按照從右至左的方式入棧,函式本身不清理棧,此工作由呼叫者負責,返回值在eax中。由於由呼叫者清理棧,所以允許可變引數函式存在,如int sprintf(char* buffer,const char* format,...);。

2、__stdcall

__stdcall 很多時候被稱為 pascal 呼叫約定。pascal 語言是早期很常見的一種教學用計算機程式語言,其語法嚴謹。引數按照從右至左的方式入棧,函式自身清理堆疊,返回值在eax中。

3、__fastcall

顧名思義,__fastcall 的特點就是快,因為它通過 cpu 暫存器來傳遞引數。他用 eax 和 edx 傳送前兩個雙字(dword)或更小的引數,剩下的引數按照從右至左的方式入棧,函式自身清理堆疊,返回值在 eax 中。

4、naked

naked 是乙個很少見的呼叫約定,一般不建議使用。編譯器不會給這種函式增加初始化和清理**,更特殊的是,你不能用return返回返回值,只能用插入彙編返回結果,此呼叫約定必須跟 __declspec 同時使用。例如定義乙個求和程式,如__declspec(naked) int  add(int a,int b);。

5、__pascal

這是 pascal 語言的呼叫約定,跟 __stdcall 一樣,引數按照從右至左的方式入棧,函式自身清理堆疊,返回值在eax中。vc 中已經廢棄了這種呼叫方式,因此在寫 vc 程式時,建議使用 __stdcall 代替。

6、__thiscall

這是 c++ 語言特有的一種呼叫方式,用於類成員函式的呼叫約定。如果引數確定,this 指標存放於 ecx 暫存器,函式自身清理堆疊;如果引數不確定,this指標在所有引數入棧後再入棧,呼叫者清理棧。__thiscall 不是關鍵字,程式設計師不能使用。引數按照從右至左的方式入棧。

C C 呼叫約定和名字約定

呼叫約定 cdecl stdcall 與 fastcall 三者都是呼叫約定 calling convention 它決定以下內容 1 函式引數的壓棧順序,2 由呼叫者還是被呼叫者把引數彈出棧,3 以及產生函式修飾名的方法。1 cdecl是c和c 程式的預設呼叫方式。每乙個呼叫它的函式都包含清空堆疊...

C C 函式呼叫約定

c c 函式呼叫約定 關於c c 函式呼叫約定,大多數時候並不會影響程式邏輯,但遇到跨語言程式設計時,了解一下還是有好處的。vc 中預設呼叫是 cdecl 方式,windows api 使用 stdcall 呼叫方式,在dll 匯出函式中,為了跟windows api 保持一致,建議使用 stdca...

C C 函式呼叫約定

關於 c c 函式呼叫約定,大多數時候並不會影響程式邏輯,但遇到跨語言程式設計時,了解一下還是有好處的。vc 中預設呼叫是 cdecl 方式,windows api 使用 stdcall 呼叫方式,在 dll 匯出函式中,為了跟 windows api 保持一致,建議使用 stdcall 方式。呼叫...