青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

__stdcall和__cdecl兩者的區(qū)別;
#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
幾乎我們寫的每一個(gè)WINDOWS API函數(shù)都是__stdcall類型的,首先,需要了解兩者之間的區(qū)別: WINDOWS的函數(shù)調(diào)用時(shí)需要用到棧(STACK,一種先入后出的存儲(chǔ)結(jié)構(gòu))。當(dāng)函數(shù)調(diào)用完成后,棧需要清除,這里就是問(wèn)題的關(guān)鍵,如何清除??如果我們的函數(shù)使用了_cdecl,那么棧的清除工作是由調(diào)用者,用COM的術(shù)語(yǔ)來(lái)講就是客戶來(lái)完成的。這樣帶來(lái)了一個(gè)棘手的問(wèn)題,不同的編譯器產(chǎn)生棧的方式不盡相同,那么調(diào)用者能否正常的完成清除工作呢?答案是不能。如果使用__stdcall,上面的問(wèn)題就解決了,函數(shù)自己解決清除工作。所以,在跨(開(kāi)發(fā))平臺(tái)的調(diào)用中,我們都使用__stdcall(雖然有時(shí)是以 WINAPI的樣子出現(xiàn))。那么為什么還需要_cdecl呢?當(dāng)我們遇到這樣的函數(shù)如fprintf()它的參數(shù)是可變的,不定長(zhǎng)的,被調(diào)用者事先無(wú)法知道參數(shù)的長(zhǎng)度,事后的清除工作也無(wú)法正常的進(jìn)行,因此,這種情況我們只能使用_cdecl。到這里我們有一個(gè)結(jié)論,如果你的程序中沒(méi)有涉及可變參數(shù),最好使用__stdcall關(guān)鍵字。
2.
__cdecl,__stdcall是聲明的函數(shù)調(diào)用協(xié)議.主要是傳參和彈棧方面的不同.一般c++用的是__cdecl,windows里大都用的是__stdcall(API)
__cdecl 是C/C++和MFC程序默認(rèn)使用的調(diào)用約定,也可以在函數(shù)聲明時(shí)加上__cdecl關(guān)鍵字來(lái)手工指定。采用__cdecl約定時(shí),函數(shù)參數(shù)按照從右到左的順序入棧,并且由調(diào)用函數(shù)者把參數(shù)彈出棧以清理堆棧。因此,實(shí)現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定。由于每一個(gè)使用__cdecl約定的函數(shù)都要包含清理堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會(huì)比較大。__cdecl可以寫成_cdecl。
__stdcall調(diào)用約定用于調(diào)用Win32 API函數(shù)。采用__stdcall約定時(shí),函數(shù)參數(shù)按照從右到左的順序入棧,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的棧,函數(shù)參數(shù)個(gè)數(shù)固定。由于函數(shù)體本身知道傳進(jìn)來(lái)的參數(shù)個(gè)數(shù),因此被調(diào)用的函數(shù)可以在返回前用一條ret n指令直接清理傳遞參數(shù)的堆棧。__stdcall可以寫成_stdcall。
__fastcall 約定用于對(duì)性能要求非常高的場(chǎng)合。__fastcall約定將函數(shù)的從左邊開(kāi)始的兩個(gè)大小不大于4個(gè)字節(jié)(DWORD)的參數(shù)分別放在ECX和EDX寄存器,其余的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的堆棧。__fastcall可以寫成_fastcall
3.
__stdcall:
_stdcall 調(diào)用約定相當(dāng)于16位動(dòng)態(tài)庫(kù)中經(jīng)常使用的PASCAL調(diào)用約定。
 
在32位的VC++5.0中PASCAL調(diào)用約定不再被支持(實(shí)際上它已被定義為 __stdcall。除了__pascal外,__fortran和__syscall也不被支持),取而代之的是__stdcall調(diào)用約定。兩者實(shí)質(zhì)上是一致的,即函數(shù)的參數(shù)自右向左通過(guò)棧傳遞,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧,但不同的是函數(shù)名的修飾部分(關(guān)于函數(shù)名的修飾部分在后面將詳細(xì)說(shuō)明)。
_stdcall是Pascal程序的缺省調(diào)用方式,通常用于Win32 Api中,函數(shù)采用從右到左的壓棧方式,自己在退出時(shí)清空堆棧。VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。
_cdecl:
_cdecl c調(diào)用約定, 按從右至左的順序壓參數(shù)入棧,由調(diào)用者把參數(shù)彈出棧。對(duì)于傳送參數(shù)的內(nèi)存棧是由調(diào)用者來(lái)維護(hù)的(正因?yàn)槿绱耍瑢?shí)現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定)。另外,在函數(shù)名修飾約定方面也有所不同。
_cdecl是C和C++程序的缺省調(diào)用方式。每一個(gè)調(diào)用它的函數(shù)都包含清空堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會(huì)比調(diào)用_stdcall函數(shù)的大。函數(shù)采用從右到左的壓棧方式。VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴。是MFC缺省調(diào)用約定。
__fastcall:
__fastcall調(diào)用約定是"人"如其名,它的主要特點(diǎn)就是快,因?yàn)樗峭ㄟ^(guò)寄存器來(lái)傳送參數(shù)的(實(shí)際上,它用ECX和EDX傳送前兩個(gè)雙字(DWORD)或更小的參數(shù),剩下的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧),在函數(shù)名修飾約定方面,它和前兩者均不同。
_fastcall方式的函數(shù)采用寄存器傳遞參數(shù),VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上"@"前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。
thiscall:
thiscall僅僅應(yīng)用于"C++"成員函數(shù)。this指針存放于CX寄存器,參數(shù)從右到左壓。thiscall不是關(guān)鍵詞,因此不能被程序員指定。
naked call:
采用1-4的調(diào)用約定時(shí),如果必要的話,進(jìn)入函數(shù)時(shí)編譯器會(huì)產(chǎn)生代碼來(lái)保存ESI,EDI,EBX,EBP寄存器,退出函數(shù)時(shí)則產(chǎn)生代碼恢復(fù)這些寄存器的內(nèi)容。
naked call不產(chǎn)生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。
另附:
關(guān)鍵字 __stdcall、__cdecl和__fastcall可以直接加在要輸出的函數(shù)前,也可以在編譯環(huán)境的Setting...\C/C++ \Code Generation項(xiàng)選擇。當(dāng)加在輸出函數(shù)前的關(guān)鍵字與編譯環(huán)境中的選擇不同時(shí),直接加在輸出函數(shù)前的關(guān)鍵字有效。它們對(duì)應(yīng)的命令行參數(shù)分別為/Gz、 /Gd和/Gr。缺省狀態(tài)為/Gd,即__cdecl。
要完全模仿PASCAL調(diào)用約定首先必須使用__stdcall調(diào)用約定,至于函數(shù)名修飾約定,可以通過(guò)其它方法模仿。還有一個(gè)值得一提的是WINAPI宏,Windows.h支持該宏,它可以將出函數(shù)翻譯成適當(dāng)?shù)恼{(diào)用約定,在WIN32中,它被定義為_(kāi)_stdcall。使用WINAPI宏可以創(chuàng)建自己的APIs。
名字修飾約定
1、修飾名(Decoration name)
“C” 或者“C++”函數(shù)在內(nèi)部(編譯和鏈接)通過(guò)修飾名識(shí)別。修飾名是編譯器在編譯函數(shù)定義或者原型時(shí)生成的字符串。有些情況下使用函數(shù)的修飾名是必要的,如在模塊定義文件里頭指定輸出“C++”重載函數(shù)、構(gòu)造函數(shù)、析構(gòu)函數(shù),又如在匯編代碼里調(diào)用“C””或“C++”函數(shù)等。
修飾名由函數(shù)名、類名、調(diào)用約定、返回類型、參數(shù)等共同決定。
2、名字修飾約定隨調(diào)用約定和編譯種類(C或C++)的不同而變化。函數(shù)名修飾約定隨編譯種類和調(diào)用約定的不同而不同,下面分別說(shuō)明。
a、C編譯時(shí)函數(shù)名修飾約定規(guī)則:
__stdcall調(diào)用約定在輸出函數(shù)名前加上一個(gè)下劃線前綴,后面加上一個(gè)“@”符號(hào)和其參數(shù)的字節(jié)數(shù),格式為_functionname@number
__cdecl調(diào)用約定僅在輸出函數(shù)名前加上一個(gè)下劃線前綴,格式為_(kāi)functionname。
__fastcall調(diào)用約定在輸出函數(shù)名前加上一個(gè)“@”符號(hào),后面也是一個(gè)“@”符號(hào)和其參數(shù)的字節(jié)數(shù),格式為@functionname@number。
它們均不改變輸出函數(shù)名中的字符大小寫,這和PASCAL調(diào)用約定不同,PASCAL約定輸出的函數(shù)名無(wú)任何修飾且全部大寫。
b、C++編譯時(shí)函數(shù)名修飾約定規(guī)則:
__stdcall調(diào)用約定:
1、以“?”標(biāo)識(shí)函數(shù)名的開(kāi)始,后跟函數(shù)名;
2、函數(shù)名后面以“@@YG”標(biāo)識(shí)參數(shù)表的開(kāi)始,后跟參數(shù)表;
3、參數(shù)表以代號(hào)表示:
X--void ,
D--char,
E--unsigned char,
F--short,
H--int,
I--unsigned int,
J--long,
K--unsigned long,
M--float,
N--double,
_N--bool,
....
PA--表示指針,后面的代號(hào)表明指針類型,如果相同類型的指針連續(xù)出現(xiàn),以“0”代替,一個(gè)“0”代表一次重復(fù);
4、參數(shù)表的第一項(xiàng)為該函數(shù)的返回值類型,其后依次為參數(shù)的數(shù)據(jù)類型,指針標(biāo)識(shí)在其所指數(shù)據(jù)類型前;
5、參數(shù)表后以“@Z”標(biāo)識(shí)整個(gè)名字的結(jié)束,如果該函數(shù)無(wú)參數(shù),則以“Z”標(biāo)識(shí)結(jié)束。
其格式為“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,例如
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z
void Test2() -----“?Test2@@YGXXZ
__cdecl調(diào)用約定:
規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開(kāi)始標(biāo)識(shí)由上面的“@@YG”變?yōu)?a href="mailto:“@@YA">“@@YA”。
__fastcall調(diào)用約定:
規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開(kāi)始標(biāo)識(shí)由上面的“@@YG”變?yōu)?a href="mailto:“@@YI">“@@YI”。
VC++對(duì)函數(shù)的省缺聲明是“__cedcl“,將只能被C/C++調(diào)用.
CB在輸出函數(shù)聲明時(shí)使用4種修飾符號(hào)
//__cdecl
cb的默認(rèn)值,它會(huì)在輸出函數(shù)名前加_,并保留此函數(shù)名不變,參數(shù)按照從右到左的順序依次傳遞給棧,也可以寫成_cdecl和cdecl形式。
//__fastcall
她修飾的函數(shù)的參數(shù)將盡肯呢感地使用寄存器來(lái)處理,其函數(shù)名前加@,參數(shù)按照從左到右的順序壓棧;
//__pascal
它說(shuō)明的函數(shù)名使用Pascal格式的命名約定。這時(shí)函數(shù)名全部大寫。參數(shù)按照從左到右的順序壓棧;
//__stdcall
使用標(biāo)準(zhǔn)約定的函數(shù)名。函數(shù)名不會(huì)改變。使用__stdcall修飾時(shí)。參數(shù)按照由右到左的順序壓棧,也可以是_stdcall;
VC++對(duì)函數(shù)的省缺聲明是"__cedcl",將只能被C/C++調(diào)用.
 
注意:
1、_beginthread需要__cdecl的線程函數(shù)地址,_beginthreadex和CreateThread需要__stdcall的線程函數(shù)地址。
2、一般WIN32的函數(shù)都是__stdcall。而且在Windef.h中有如下的定義:
 #define CALLBACK __stdcall
 #define WINAPI  __stdcall
3、extern "C" _declspec(dllexport) int __cdecl Add(int a, int b);
   typedef int (__cdecl*FunPointer)(int a, int b);
   修飾符的書寫順序如上。
4、extern "C"的作用:如果Add(int a, int b)是在c語(yǔ)言編譯器編譯,而在c++文件使用,則需要在c++文件中聲明:extern "C" Add(int a, int b),因?yàn)閏編譯器和c++編譯器對(duì)函數(shù)名的解釋不一樣(c++編譯器解釋函數(shù)名的時(shí)候要考慮函數(shù)參數(shù),這樣是了方便函數(shù)重載,而在c語(yǔ)言中不存在函數(shù)重載的問(wèn)題),使用extern "C",實(shí)質(zhì)就是告訴c++編譯器,該函數(shù)是c庫(kù)里面的函數(shù)。如果不使用extern "C"則會(huì)出現(xiàn)鏈接錯(cuò)誤。
一般象如下使用:
#ifdef _cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
#ifdef _cplusplus
extern "C"{
#endif
 EXTERN_C int func(int a, int b);
#ifdef _cplusplus
}
#endif
5、MFC提供了一些宏,可以使用AFX_EXT_CLASS來(lái)代替__declspec(DLLexport),并修飾類名,從而導(dǎo)出類,AFX_API_EXPORT來(lái)修飾函數(shù),AFX_DATA_EXPORT來(lái)修飾變量
AFX_CLASS_IMPORT:__declspec(DLLexport)
AFX_API_IMPORT:__declspec(DLLexport)
AFX_DATA_IMPORT:__declspec(DLLexport)
AFX_CLASS_EXPORT:__declspec(DLLexport)
AFX_API_EXPORT:__declspec(DLLexport)
AFX_DATA_EXPORT:__declspec(DLLexport)
AFX_EXT_CLASS:#ifdef _AFXEXT
   AFX_CLASS_EXPORT
        #else
   AFX_CLASS_IMPORT
6、DLLMain負(fù)責(zé)初始化(Initialization)和結(jié)束 (Termination)工作,每當(dāng)一個(gè)新的進(jìn)程或者該進(jìn)程的新的線程訪問(wèn)DLL時(shí),或者訪問(wèn)DLL的每一個(gè)進(jìn)程或者線程不再使用DLL或者結(jié)束時(shí),都會(huì)調(diào)用DLLMain。但是,使用TerminateProcess或TerminateThread結(jié)束進(jìn)程或者線程,不會(huì)調(diào)用DLLMain。
7、一個(gè)DLL在內(nèi)存中只有一個(gè)實(shí)例
DLL程序和調(diào)用其輸出函數(shù)的程序的關(guān)系:
1)、DLL與進(jìn)程、線程之間的關(guān)系
DLL模塊被映射到調(diào)用它的進(jìn)程的虛擬地址空間。
DLL使用的內(nèi)存從調(diào)用進(jìn)程的虛擬地址空間分配,只能被該進(jìn)程的線程所訪問(wèn)。
DLL的句柄可以被調(diào)用進(jìn)程使用;調(diào)用進(jìn)程的句柄可以被DLL使用。
DLLDLL可以有自己的數(shù)據(jù)段,但沒(méi)有自己的堆棧,使用調(diào)用進(jìn)程的棧,與調(diào)用它的應(yīng)用程序相同的堆棧模式。
2)、關(guān)于共享數(shù)據(jù)段
DLL定義的全局變量可以被調(diào)用進(jìn)程訪問(wèn);DLL可以訪問(wèn)調(diào)用進(jìn)程的全局?jǐn)?shù)據(jù)。使用同一 DLL的每一個(gè)進(jìn)程都有自己的DLL全局變量實(shí)例。如果多個(gè)線程并發(fā)訪問(wèn)同一變量,則需要使用同步機(jī)制;對(duì)一個(gè)DLL的變量,如果希望每個(gè)使用DLL的線程都有自己的值,則應(yīng)該使用線程局部存儲(chǔ)(TLS,Thread Local Strorage)。
Posted on 2010-08-30 10:36 鄭興鋒 閱讀(1664) 評(píng)論(0)  編輯 收藏 引用

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲免费在线看| 亚洲欧美日韩系列| 亚洲乱码一区二区| 在线观看欧美日韩| 亚洲国产精品久久久久| 亚洲国产国产亚洲一二三| 亚洲大片av| 亚洲欧洲日产国产网站| 亚洲精品国产品国语在线app| 亚洲国产精品成人精品| 日韩亚洲在线观看| 亚洲一区在线观看免费观看电影高清| 亚洲欧美不卡| 久久久久久久欧美精品| 欧美韩日亚洲| 中文日韩欧美| 久久久999精品| 欧美日韩亚洲免费| 国产欧美日韩专区发布| 亚洲福利国产| 亚洲一区二区三区在线| 久久午夜影视| 亚洲精品国产无天堂网2021| 一区二区三区久久精品| 午夜精品在线视频| 欧美二区在线播放| 国产午夜精品麻豆| 亚洲裸体视频| 久久精品国产久精国产爱| 亚洲黄色在线看| 欧美一级久久| 欧美日韩一区二区三| 激情久久五月天| 午夜一区二区三区在线观看| 亚洲成在线观看| 午夜欧美大尺度福利影院在线看 | 国产精品尤物| 亚洲国产二区| 久久久777| 亚洲欧美日韩天堂| 欧美精品一区二区蜜臀亚洲| 国产精品久久久久毛片软件| 在线观看亚洲视频啊啊啊啊| 亚洲在线1234| 亚洲人成久久| 蜜臀久久99精品久久久久久9| 国产欧美日韩精品专区| 亚洲一区二三| 亚洲另类在线视频| 美女999久久久精品视频| 国产精品国产三级国产aⅴ9色| 亚洲日本无吗高清不卡| 久久精品国语| 午夜视频久久久久久| 国产精品成人国产乱一区| 日韩香蕉视频| 亚洲国产精品电影| 狂野欧美激情性xxxx| 国产专区综合网| 中国成人亚色综合网站| 亚洲人成网在线播放| 欧美va天堂va视频va在线| 在线欧美福利| 欧美大香线蕉线伊人久久国产精品| 欧美怡红院视频| 国产丝袜美腿一区二区三区| 亚洲国产精品一区二区久| 久久人人爽人人| 红桃视频一区| 久久综合久久美利坚合众国| 欧美一区影院| 国产一区免费视频| 久久久精品国产一区二区三区| 亚洲欧美中文在线视频| 国产午夜精品视频免费不卡69堂| 午夜一区二区三区不卡视频| 亚洲欧美99| 国产一区二区精品久久91| 亚洲欧美一区二区原创| 亚洲一区在线看| 国产综合第一页| 女女同性女同一区二区三区91| 久久久天天操| 91久久极品少妇xxxxⅹ软件| 亚洲成人自拍视频| 欧美精品日日鲁夜夜添| 亚洲一区二区在线看| 在线视频精品| 国产一区二区精品久久| 美女网站在线免费欧美精品| 欧美激情视频给我| 欧美一区二区视频网站| 欧美在线播放视频| 亚洲精品老司机| 亚洲一区二区3| 亚洲第一页在线| 99热免费精品| 精品成人a区在线观看| 久久综合亚洲社区| 国产欧美一区二区在线观看| 老司机免费视频一区二区| 老司机午夜精品视频| 一本色道久久综合精品竹菊| 亚洲与欧洲av电影| 在线精品亚洲| 99热精品在线观看| 亚洲第一福利在线观看| 在线亚洲一区二区| 136国产福利精品导航网址| 亚洲裸体视频| 国产综合久久久久久鬼色| 久久精品最新地址| 欧美精品一区二区三区视频| 久久久久久亚洲综合影院红桃| 欧美福利视频在线观看| 久久久久久久久久久久久久一区| 欧美日韩免费观看一区三区| 欧美在线观看一区二区| 欧美日韩国产综合视频在线| 免费观看久久久4p| 国产精品美女久久久免费| 欧美成人精品一区二区三区| 国产欧美日韩综合| 亚洲一区欧美激情| 一个色综合av| 免费成人高清| 麻豆免费精品视频| 国产一区二区三区免费在线观看| 亚洲精品日韩在线观看| 亚洲国产一区二区三区青草影视| 欧美亚洲综合久久| 欧美有码在线视频| 国产精品乱码一区二区三区 | 久久亚洲私人国产精品va| 欧美日韩国产一区二区三区| 欧美成年人视频网站| 国内精品久久久久久| 欧美一区影院| 久久免费高清| 韩国精品在线观看| 久久九九久精品国产免费直播| 久久综合综合久久综合| 红桃视频一区| 久久在线视频在线| 欧美国产视频日韩| 亚洲精品影院| 欧美日韩亚洲国产精品| 国产精品99久久久久久久久久久久| 亚洲午夜伦理| 国产精品久久久久久模特| 亚洲专区在线视频| 久久在线视频| 亚洲九九精品| 欧美系列精品| 亚洲欧美日韩一区在线| 久久香蕉国产线看观看网| 在线播放亚洲一区| 欧美成人免费观看| 宅男精品视频| 久久久久久久久久久成人| 亚洲国产欧美一区| 欧美麻豆久久久久久中文| 99国内精品久久久久久久软件| 亚洲综合日韩在线| 国语自产在线不卡| 亚洲午夜精品久久| 国产乱码精品一区二区三区不卡| 在线亚洲一区观看| 久久久久久久综合色一本| 亚洲国产婷婷香蕉久久久久久| 欧美精品在线观看| 亚洲欧美精品在线观看| 欧美暴力喷水在线| 亚洲一区二三| 韩国av一区二区| 欧美日韩国产成人在线观看| 欧美一级成年大片在线观看| 亚洲国产精品一区二区第四页av | 欧美成人69| 一区二区三区免费网站| 久久久久久久久久码影片| 亚洲国产欧美一区| 国产精品午夜在线观看| 免费日韩精品中文字幕视频在线| 国产精品99久久久久久有的能看| 久久视频国产精品免费视频在线| 一本色道久久88综合亚洲精品ⅰ| 国产一区二区成人| 欧美日韩一区二区在线观看视频| 久久久天天操| 亚洲专区国产精品| 亚洲精品一区二区三区婷婷月| 久久精品女人的天堂av| 中文精品视频一区二区在线观看| 国内免费精品永久在线视频| 欧美日本精品| 免费久久99精品国产自在现线| 亚洲欧美在线一区| 亚洲一区激情| 一本色道久久综合亚洲精品不|