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