• <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>

            把握命運(yùn),追逐夢(mèng)想

            對(duì)自己所做的事要有興趣,同時(shí)還要能夠堅(jiān)持不懈

            統(tǒng)計(jì)

            留言簿(1)

            閱讀排行榜

            評(píng)論排行榜

            __cdecl、__stdcall、__fastcall

            1.這三個(gè)修飾符的基本意思
               __cdecl:C調(diào)用方式,VC默認(rèn)使用該方式,參數(shù)從右向左傳遞,參數(shù)個(gè)數(shù)可變,棧的初始和清理由調(diào)用者完成
               __stdcall:標(biāo)準(zhǔn)調(diào)用方式,多種語言使用這種調(diào)用方式,參數(shù)從右向左傳遞,參數(shù)個(gè)數(shù)不可變,棧的初始和清理由被調(diào)用者完成
               __fastcall:參數(shù)盡量使用寄存器傳遞,很少用到,這里不予討論。

            2.這三個(gè)修飾符的使用位置

               這三個(gè)修飾符要用在類型名之后,不能用在類型名之前,否則語法無法識(shí)別,容易被編譯器誤以為是默認(rèn)int錯(cuò)誤。

               這三個(gè)修飾符都不能用于變量,如果使用會(huì)有警告,如下:
               
            編譯器警告(等級(jí) 1)C4229
            對(duì)數(shù)據(jù)聲明使用 Microsoft 修飾符(如 __cdecl)是已過時(shí)的做法。
               這三個(gè)函數(shù)只能用在函數(shù)前面,不能用于別的東西上,可以用在成員函數(shù)上,但是這個(gè)不像__declspec(dllimport)一樣,__declspec(dllimport)可以用在類聲明的前面,這樣整個(gè)類都被導(dǎo)出,包括成員變量和函數(shù),而這幾個(gè)調(diào)用修飾符只能直接用在類聲明體中的成員函數(shù)的前面(而且函數(shù)定義前也需要),來說明成員函數(shù)的調(diào)用方式。下表是產(chǎn)生規(guī)則:

            C 和C++ 對(duì)應(yīng)不同的調(diào)用約定,產(chǎn)生的修飾符也各不相同,對(duì)于函數(shù)test(void)如下:
            調(diào)用約定 extern "C" 或 .c 文件 .cpp、.cxx 或 /TP

            C 命名約定 (__cdecl)

            _test

            ?test@@ZAXXZ

            Fastcall 命名約定 (__fastcall)

            @test@0

            ?test@@YIXXZ

            標(biāo)準(zhǔn)調(diào)用命名約定 (__stdcall)

            _test@0

            ?test@@YGXXZ

            第二列,也就是C風(fēng)格的情況下,@后面的數(shù)字表述所有參數(shù)的字節(jié)數(shù)之和。
            第三列,也就是CPP風(fēng)格的情況下,修飾符有些復(fù)雜,以后補(bǔ)充吧。

            以前面的一片隨筆PureDllApp為例,VC9.0進(jìn)行分析:
            1、extern "C"作用下:
             (1)__cdecl作用下(由于VC默認(rèn)就是這種調(diào)用方式,所以這里就不給出代碼,和前面的一片PureDllApp的代碼一樣):
            PureApp.exe對(duì)PureDll.dll的導(dǎo)入修飾符如下:
               4 fnPureDll
               
            6 nPureDll
               
            1 ??1CPureDll@@QAE@XZ
               
            3 ?setValue@CPureDll@@QAEXH@Z
               
            0 ??0CPureDll@@QAE@H@Z
               
            5 g_pureDll
            PureDll.lib的導(dǎo)出修飾符如下:

                              
            ??0CPureDll@@QAE@H@Z (public: __thiscall CPureDll::CPureDll(int))
                              
            ??1CPureDll@@QAE@XZ (public: __thiscall CPureDll::~CPureDll(void))
                              
            ??4CPureDll@@QAEAAV0@ABV0@@Z (publicclass CPureDll & __thiscall CPureDll::operator=(class CPureDll const &))
                              
            ?setValue@CPureDll@@QAEXH@Z (publicvoid __thiscall CPureDll::setValue(int))
                              _fnPureDll
                              _g_pureDll
                              _nPureDll
            PureDll.dll的導(dǎo)出修飾符如下:
                ordinal hint RVA      name

                      
            1    0 00011005 ??0CPureDll@@QAE@H@Z = @ILT+0(??0CPureDll@@QAE@H@Z)
                      
            2    1 000110B9 ??1CPureDll@@QAE@XZ = @ILT+180(??1CPureDll@@QAE@XZ)
                      
            3    2 000110C3 ??4CPureDll@@QAEAAV0@ABV0@@Z = @ILT+190(??4CPureDll@@QAEAAV0@ABV0@@Z)
                      
            4    3 00011168 ?setValue@CPureDll@@QAEXH@Z = @ILT+355(?setValue@CPureDll@@QAEXH@Z)
                      
            5    4 000110EB fnPureDll = @ILT+230(_fnPureDll)
                      
            6    5 00019138 g_pureDll = _g_pureDll
                      
            7    6 00019000 nPureDll = _nPureDll
            (2)__stdcall作用下(調(diào)用方式的改變?cè)诤瘮?shù)聲明和定義之前都要使用,下面先是發(fā)生改變的頭文件,cpp文件中在函數(shù)定義前做一樣的修改即可):
            需要注意的就是調(diào)用修飾符只能用在函數(shù)和成員函數(shù)的前面,而且要在返回值類型之后的位置。
            // 下列 ifdef 塊是創(chuàng)建使從 DLL 導(dǎo)出更簡(jiǎn)單的
            // 宏的標(biāo)準(zhǔn)方法。此 DLL 中的所有文件都是用命令行上定義的 PUREDLL_EXPORTS
            // 符號(hào)編譯的。在使用此 DLL 的
            // 任何其他項(xiàng)目上不應(yīng)定義此符號(hào)。這樣,源文件中包含此文件的任何其他項(xiàng)目都會(huì)將
            // PUREDLL_API 函數(shù)視為是從 DLL 導(dǎo)入的,而此 DLL 則將用此宏定義的
            // 符號(hào)視為是被導(dǎo)出的。

            #ifdef __cplusplus
            extern "C"
            {
            #endif
            #ifdef PUREDLL_EXPORTS
            #define PUREDLL_API __declspec(dllexport)
            #else
            #define PUREDLL_API __declspec(dllimport)
            #endif

                
            // 此類是從 PureDll.dll 導(dǎo)出的
                class PUREDLL_API CPureDll {
                
            public:
                    __stdcall CPureDll(
            int num);
                    
            // TODO: 在此添加您的方法。

                    __stdcall 
            ~CPureDll(void);
                    
            void __stdcall setValue(int value);
                
            private:
                    
            int m_num;
                    
            int *m_p;
                }
            ;

                
            extern PUREDLL_API int nPureDll;

                
            extern PUREDLL_API CPureDll g_pureDll;

                PUREDLL_API 
            int __stdcall fnPureDll(void);

            #ifdef __cplusplus
            }

            #endif



            PureApp.exe對(duì)PureDll.dll的導(dǎo)入修飾符如下:
               5 g_pureDll
               
            1 ??1CPureDll@@QAE@XZ
               
            4 _fnPureDll@0
               
            3 ?setValue@CPureDll@@QAGXH@Z
               
            0 ??0CPureDll@@QAE@H@Z
               
            6 nPureDll
            PureDll.lib的導(dǎo)出修飾符如下:
                              ??0CPureDll@@QAE@H@Z (public: __thiscall CPureDll::CPureDll(int))
                              
            ??1CPureDll@@QAE@XZ (public: __thiscall CPureDll::~CPureDll(void))
                              
            ??4CPureDll@@QAEAAV0@ABV0@@Z (publicclass CPureDll & __thiscall CPureDll::operator=(class CPureDll const &))
                              
            ?setValue@CPureDll@@QAGXH@Z (publicvoid __stdcall CPureDll::setValue(int))
                              _fnPureDll@
            0
                              _g_pureDll
                              _nPureDll
            PureDll.dll的導(dǎo)出修飾符如下:
                ordinal hint RVA      name

                      
            1    0 00011005 ??0CPureDll@@QAE@H@Z = @ILT+0(??0CPureDll@@QAE@H@Z)
                      
            2    1 000110C3 ??1CPureDll@@QAE@XZ = @ILT+190(??1CPureDll@@QAE@XZ)
                      
            3    2 000110CD ??4CPureDll@@QAEAAV0@ABV0@@Z = @ILT+200(??4CPureDll@@QAEAAV0@ABV0@@Z)
                      
            4    3 0001100F ?setValue@CPureDll@@QAGXH@Z = @ILT+10(?setValue@CPureDll@@QAGXH@Z)
                      
            5    4 0001105A _fnPureDll@0 = @ILT+85(_fnPureDll@0)
                      
            6    5 00019138 g_pureDll = _g_pureDll
                      
            7    6 00019000 nPureDll = _nPureDll

            比較上面的兩組之間的差別,就可以發(fā)現(xiàn)__cdecl和__stdcall之間的差別。
            第一點(diǎn),構(gòu)造函數(shù)在這兩種調(diào)用方式中的產(chǎn)生的修飾符相同,其實(shí)產(chǎn)生的修飾符不是這兩種的任何一種,而是__thiscall的修飾符,從PureDll.lib的后面括號(hào)中可以看出來,而且VC9.0中在構(gòu)造函數(shù)前面使用__cdecl會(huì)直接產(chǎn)生編譯時(shí)警告c4166,如下:
            編譯器警告(等級(jí) 1)C4166
            構(gòu)造函數(shù)
            /析構(gòu)函數(shù)的非法調(diào)用約定 

            構(gòu)造函數(shù)和析構(gòu)函數(shù)不能有非平臺(tái)默認(rèn)的調(diào)用約定(顯式指定 __clrcall 時(shí)除外)。

            再對(duì)照第一組中setValue函數(shù)在PureDll.lib中產(chǎn)生的修飾符,可以知道類成員函數(shù)默認(rèn)使用__thiscall修飾符,即使編譯器選項(xiàng)中選擇了__cdecl,也就是說構(gòu)造函數(shù)和析構(gòu)函數(shù)必須使用當(dāng)前平臺(tái)默認(rèn)的調(diào)用方式----__thiscall,其它的成員函數(shù)可以通過在函數(shù)名前(聲明和定義)強(qiáng)制加上指定的調(diào)用方式即可,編譯器選項(xiàng)中的調(diào)用方式不行(這里指定的方式只是對(duì)非成員函數(shù)有效的,成員函數(shù)會(huì)默認(rèn)使用__thiscall)。
            其實(shí)__thiscall和__stdcall差別不大,都是被調(diào)用者控制棧的初始和清理,只不過前者的this指針放在寄存器中,而后者的放在棧里。所以對(duì)于成員函數(shù)一般不要指定調(diào)用方式,使用默認(rèn)的__shicall即可,除非要做參數(shù)數(shù)量可變的成員函數(shù),不過這種函數(shù)盡量避免。
            最后補(bǔ)充上setValue函數(shù)的__cdecl調(diào)用方式產(chǎn)生的修飾符:
                              ?setValue@CPureDll@@QAAXH@Z (publicvoid __cdecl CPureDll::setValue(int))

            2.對(duì)應(yīng)上面的extern "C",下面是cpp(去掉extern "C")下對(duì)應(yīng)上面的修飾符:
            (1)__cdecl作用下:
            PureApp.exe對(duì)PureDll.dll的導(dǎo)入修飾符如下:
                3 ?fnPureDll@@YAHXZ
                
            5 ?nPureDll@@3HA
                
            1 ??1CPureDll@@QAE@XZ
                
            6 ?setValue@CPureDll@@QAEXH@Z
                
            0 ??0CPureDll@@QAE@H@Z
                
            4 ?g_pureDll@@3VCPureDll@@A
            PureDll.lib的導(dǎo)出修飾符如下:
                              ??0CPureDll@@QAE@H@Z (public: __thiscall CPureDll::CPureDll(int))
                              
            ??1CPureDll@@QAE@XZ (public: __thiscall CPureDll::~CPureDll(void))
                              
            ??4CPureDll@@QAEAAV0@ABV0@@Z (publicclass CPureDll & __thiscall CPureDll::operator=(class CPureDll const &))
                              
            ?fnPureDll@@YAHXZ (int __cdecl fnPureDll(void))
                              
            ?g_pureDll@@3VCPureDll@@A (class CPureDll g_pureDll)
                              
            ?nPureDll@@3HA (int nPureDll)
                              
            ?setValue@CPureDll@@QAEXH@Z (publicvoid __thiscall CPureDll::setValue(int))
            PureDll.dll的導(dǎo)出修飾符如下:
                ordinal hint RVA      name

                      
            1    0 00011005 ??0CPureDll@@QAE@H@Z = @ILT+0(??0CPureDll@@QAE@H@Z)
                      
            2    1 000110B9 ??1CPureDll@@QAE@XZ = @ILT+180(??1CPureDll@@QAE@XZ)
                      
            3    2 000110C3 ??4CPureDll@@QAEAAV0@ABV0@@Z = @ILT+190(??4CPureDll@@QAEAAV0@ABV0@@Z)
                      
            4    3 00011113 ?fnPureDll@@YAHXZ = @ILT+270(?fnPureDll@@YAHXZ)
                      
            5    4 00019138 ?g_pureDll@@3VCPureDll@@A = ?g_pureDll@@3VCPureDll@@A(class CPureDll g_pureDll)
                      
            6    5 00019000 ?nPureDll@@3HA = ?nPureDll@@3HA (int nPureDll)
                      
            7    6 00011168 ?setValue@CPureDll@@QAEXH@Z = @ILT+355(?setValue@CPureDll@@QAEXH@Z)
            (2)__stdcall作用下:
            PureApp.exe對(duì)PureDll.dll的導(dǎo)入修飾符如下:
               3 ?fnPureDll@@YGHXZ
               
            5 ?nPureDll@@3HA
               
            1 ??1CPureDll@@QAE@XZ
               
            6 ?setValue@CPureDll@@QAGXH@Z
               
            0 ??0CPureDll@@QAE@H@Z
               
            4 ?g_pureDll@@3VCPureDll@@A
            PureDll.lib的導(dǎo)出修飾符如下:
                              ??0CPureDll@@QAE@H@Z (public: __thiscall CPureDll::CPureDll(int))
                              
            ??1CPureDll@@QAE@XZ (public: __thiscall CPureDll::~CPureDll(void))
                              
            ??4CPureDll@@QAEAAV0@ABV0@@Z (publicclass CPureDll & __thiscall CPureDll::operator=(class CPureDll const &))
                              
            ?fnPureDll@@YGHXZ (int __stdcall fnPureDll(void))
                              
            ?g_pureDll@@3VCPureDll@@A (class CPureDll g_pureDll)
                              
            ?nPureDll@@3HA (int nPureDll)
                              
            ?setValue@CPureDll@@QAGXH@Z (publicvoid __stdcall CPureDll::setValue(int))
            PureDll.dll的導(dǎo)出修飾符如下:
                ordinal hint RVA      name

                      
            1    0 00011005 ??0CPureDll@@QAE@H@Z = @ILT+0(??0CPureDll@@QAE@H@Z)
                      
            2    1 000110BE ??1CPureDll@@QAE@XZ = @ILT+185(??1CPureDll@@QAE@XZ)
                      
            3    2 000110C8 ??4CPureDll@@QAEAAV0@ABV0@@Z = @ILT+195(??4CPureDll@@QAEAAV0@ABV0@@Z)
                      
            4    3 00011118 ?fnPureDll@@YGHXZ = @ILT+275(?fnPureDll@@YGHXZ)
                      
            5    4 00019138 ?g_pureDll@@3VCPureDll@@A = ?g_pureDll@@3VCPureDll@@A(class CPureDll g_pureDll)
                      
            6    5 00019000 ?nPureDll@@3HA = ?nPureDll@@3HA (int nPureDll)
                      
            7    6 0001100F ?setValue@CPureDll@@QAGXH@Z = @ILT+10(?setValue@CPureDll@@QAGXH@Z)

            補(bǔ)充一個(gè)強(qiáng)制指定__cdecl的setValue的修飾符:
                              ?setValue@CPureDll@@QAAXH@Z (publicvoid __cdecl CPureDll::setValue(int))

            cpp的__stdcall也沒有什么特別的,和extern "C"相比,沒有什么大的變化,唯一變得就是后面的字母變多了。而且能夠發(fā)現(xiàn)無論是否存在extern "C",成員函數(shù)的修飾符都沒有改變,這是因?yàn)镃語言本身沒有成員函數(shù),所以extern "C對(duì)成員函數(shù)是無效的。
            所以成員函數(shù)有兩個(gè)特殊點(diǎn):首先是extern "C"對(duì)類無效,即成員函數(shù)無效,其次是成員函數(shù)默認(rèn)是__thiscall,除非在函數(shù)前強(qiáng)制指明其他調(diào)用方式。
            暫時(shí)到這里,以后有機(jī)會(huì)再補(bǔ)充別的。

            posted on 2009-08-18 23:05 把握命運(yùn) 閱讀(1451) 評(píng)論(0)  編輯 收藏 引用


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


            97精品国产97久久久久久免费 | 99热精品久久只有精品| 久久精品国产亚洲av麻豆色欲| 亚洲国产天堂久久久久久| 欧美黑人激情性久久| 精品国产乱码久久久久久人妻 | 久久久精品午夜免费不卡| 青青草原综合久久| 热久久最新网站获取| 少妇高潮惨叫久久久久久 | 久久精品国产精品亚洲精品 | 日韩人妻无码精品久久免费一| 99久久无色码中文字幕| 久久激情五月丁香伊人| 亚洲精品无码久久久影院相关影片| 精品久久久无码人妻中文字幕豆芽| www亚洲欲色成人久久精品| 人妻无码精品久久亚瑟影视| 国内精品久久久人妻中文字幕| 久久中文字幕无码专区| 国产精品女同久久久久电影院| 久久影院亚洲一区| 91久久精品国产成人久久| 午夜天堂av天堂久久久| 日韩欧美亚洲综合久久影院Ds| 精品一区二区久久久久久久网站| 日韩精品久久久久久久电影| 久久久久久一区国产精品| MM131亚洲国产美女久久| 久久久久亚洲av成人网人人软件 | 精品久久久久久无码不卡| 99久久夜色精品国产网站| 久久国产精品无码一区二区三区| 午夜精品久久久久| 香蕉久久夜色精品国产2020| 三级片免费观看久久| 久久久久国产一区二区| 国产精品日韩深夜福利久久| 91精品日韩人妻无码久久不卡| 日韩亚洲欧美久久久www综合网| 久久夜色精品国产噜噜亚洲AV|