從寫線程函數時遇到的__stdcall談起

今天寫線程函數時,發現msdn中對ThreadProc的定義有要求: DWORD WINAPI ThreadProc( LPVOID lpParameter);
不解爲什麼要用WINAPI宏定義,查了後發現下面的定義。

於是乎需要區別 __stdcall和__cdecl兩者的區別:

#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
#define cdecl _cdecl
#ifndef CDECL
#define CDECL _cdecl
#endif

      幾乎我們寫的每一個WINDOWS API函數都是__stdcall類型的

      首先,需要了解兩者之間的區別:

      WINDOWS的函數調用時需要用到棧(STACK,一種先入後出的存儲結構)。當函數調用完成後,棧需要清理,這裏就是問題的關鍵,如何清理???

      如果我們的函數使用了_cdecl,那麼棧的清除工作是由調用者,用COM的術語來講就是客戶來完成的。這樣帶來了一個棘手的問題,不同的編譯器產生棧的方式不盡相同,那麼調用者能否正常的完成清理工作呢?答案是不能。

      如果使用__stdcall,上面的問題就解決了,函數自己解決清理工作。所以,在跨(開發)平臺的調用中,我們都使用__stdcall(雖然有時是以WINAPI的樣子出現)。

 

      那麼爲什麼還需要_cdecl呢?

      當我們遇到這樣的函數如fprintf()它的參數是可變的,不定長的,被調用者事先無法知道參數的長度,事後的清除工作也無法正常的進行,因此,這種情況我們只能使用_cdecl。

     

      到這裏我們有一個結論:如果你的程序中沒有涉及可變參數,最好使用__stdcall關鍵字。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/sailorzon/archive/2005/03/15/320103.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章