2008-11-18 21 views
119

我學習Win32編程,和WinMain原型的樣子:什麼是__stdcall?

int WINAPI WinMain (HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show) 

我困惑,這是什麼WINAPI標識符是爲發現:

#define WINAPI  __stdcall 

這是什麼呢?在返回類型之後,我對此感到困惑。 __stdcall是什麼?返回類型和函數名稱之間有什麼意義時,這意味着什麼?

+1

@AndrewProck的 「虛擬」在這種情況下,改變是可以的,但總的來說,你可以使用` `來解決最少6個字符的愚蠢(並且適得其反)。 – 2014-01-10 00:01:47

回答

137

__stdcall是用於該功能的調用約定。這會告訴編譯器適用於設置堆棧,推送參數和獲取返回值的規則。

還有一些其他的調用約定,__cdecl__thiscall__fastcall和奇妙命名爲__naked__stdcall是Win32系統調用的標準調用約定。

維基百科涵蓋details

它當你調用的代碼之外的功能(例如操作系統API)或操作系統叫你(這裏用的WinMain是這樣)主要事項。如果編譯器不知道正確的調用約定,那麼您可能會遇到非常奇怪的崩潰,因爲堆棧將無法正確管理。

+8

看到這個問題的一個非常starnge崩潰的例子http://stackoverflow.com/questions/696306/run-time-check-failure-0-loading-queryfullprocessimagename-from-kernel32-dl​​l – sharptooth 2009-04-17 04:08:14

+0

如果我沒有弄錯,那麼這些調用約定控制編譯器如何生成彙編代碼。當與彙編代碼進行交互時,注意調用約定以防止堆棧問題至關重要。 這裏有一個很好的表格,記錄一些約定:https://msdn.microsoft.com/en-us/library/984x0h58.aspx – 2015-07-24 17:03:37

31

C或C++本身沒有定義這些標識符。它們是編譯器擴展並代表某些調用約定。這決定了將參數放在哪裏,按照什麼順序,被調用的函數將找到返回地址,依此類推。例如,__fastcall表示函數的參數通過寄存器傳遞。

Wikipedia Article提供了不同的調用約定的概述發現在那裏。

15

的答案至今已覆蓋的細節,但如果你不打算下降到組裝,那麼所有你必須知道的是,無論是主叫用戶和被叫必須使用相同的調用約定,否則你」會得到很難找到的錯誤。

9

我同意迄今爲止所有答案都是正確的,但這是原因。微軟的C和C++編譯器爲應用程序的C和C++函數中的函數調用的速度提供了各種調用約定。在每種情況下,主叫方和被叫方必須就使用哪種調用約定達成一致。現在,Windows本身提供了函數(API),而且這些函數已經被編譯,所以當你調用它們時,你必須遵守它們。任何對Windows API的調用以及Windows API的回調都必須使用__stdcall約定。

4

__stdcall用於將函數參數放入堆棧。 完成該功能後,它會自動解除分配內存。 這用於固定參數。

void __stdcall fnname (int, int*) 
{ 
    ... 
} 

int main() 
{ 
    CreateThread (NULL, 0, fnname, int, int*......) 
} 

這裏fnname具有ARGS它直接推入堆棧。

1

我以前從來沒有使用這個直到今天。因爲在我的代碼中,我使用的是多線程,而我使用的多線程API是windows one(_beginthreadex)。

要啓動線程:

_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0); 

的ExecuteCommand函數MUST使用方法簽名的__stdcall關鍵字,以便beginthreadex稱之爲:

unsigned int __stdcall Scene::ExecuteCommand(void* command) 
{ 
    return system(static_cast<char*>(command)); 
}