__declspec一般是ms對標準c++語言的擴充指令.經(jīng)典的象dllexport,property(get=...)等等.不想跨平臺用用不錯.
__cdecl,__stdcall是聲明的函數(shù)調(diào)用協(xié)議.主要是傳參和彈棧方面的不同.一般c++用的是__cdecl,windows里大都用的是__stdcall(API)
函數(shù)調(diào)用規(guī)范__cdecl和__stdcall的區(qū)別一目了然(表格形式) 轉(zhuǎn)載- -
Tag:
__cdecl ??
__stdcall ??
區(qū)別 ?? ??????????????????????????????????????
? __cdecl ? | ? __stdcall |
? C和C++程序的缺省調(diào)用規(guī)范 | ? 為了使用這種調(diào)用規(guī)范,需要你明確的加上__stdcall(或WINAPI)文字。即return-type__stdcallfunction-name[(argument-list)] ? |
? 在被調(diào)用函數(shù)(Callee)返回后,由調(diào)用者(Caller)調(diào)整堆棧。 ?
調(diào)用者 ??? // call function ??? // adjust stack ?
被調(diào)用函數(shù) ??? // do work ??? // return | ? 在被調(diào)用函數(shù)(Callee)返回前,由被調(diào)用函數(shù)(Callee)調(diào)整堆棧。圖示: ?
調(diào)用者 ??? // call function ?
被調(diào)用函數(shù) ??? // do work ??? // adjust stack ??? // return |
? 因為每個調(diào)用的地方都需要生成一段調(diào)整堆棧的代碼,所以最后生成的文件較大。 ? | ? 因為調(diào)整堆棧的代碼只存在在一個地方(被調(diào)用函數(shù)的代碼內(nèi)),所以最后生成的文件較小。 |
? 函數(shù)的參數(shù)個數(shù)可變(就像printf函數(shù)一樣),因為只有調(diào)用者才知道它傳給被調(diào)用函數(shù)幾個參數(shù),才能在調(diào)用結(jié)束時適當?shù)卣{(diào)整堆棧。 ? | ? 函數(shù)的參數(shù)個數(shù)不能是可變的。 |
? 對于定義在C程序文件中的輸出函數(shù),函數(shù)名會保持原樣,不會被修飾。 對于定義在C++程序文件中的輸出函數(shù),函數(shù)名會被修飾, MSDN說Underscore character (_) is prefixed to names. 我實際測試(VC4和VC6)下來發(fā)現(xiàn)好像不是那么簡單。 可通過在前面加上extern “C”以去除函數(shù)名修飾。也可通過.def文件去除函數(shù)名修飾。 | ? 不論是C程序文件中的輸出函數(shù)還是C++程序文件中的輸出函數(shù),函數(shù)名都會被修飾。 對于定義在C程序文件中的輸出函數(shù),An
underscore (_) is prefixed to the name. The name is followed by the at
sign (@) followed by the number of bytes (in decimal) in the argument
list. 對于定義在C++程序文件中的輸出函數(shù),好像更復雜,和__cdecl的情況類似。 好像只能通過.def文件去除函數(shù)名修飾。 ? |
? _beginthread需要__cdecl的線程函數(shù)地址 ? | ? _beginthreadex和CreateThread需要__stdcall的線程函數(shù)地址 |