• <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),追逐夢想

            對自己所做的事要有興趣,同時還要能夠堅持不懈

            統(tǒng)計

            留言簿(1)

            閱讀排行榜

            評論排行榜

            __cdecl、__stdcall、__fastcall

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

            2.這三個修飾符的使用位置

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

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

            C 和C++ 對應(yīng)不同的調(diào)用約定,產(chǎn)生的修飾符也各不相同,對于函數(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對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)用方式的改變在函數(shù)聲明和定義之前都要使用,下面先是發(fā)生改變的頭文件,cpp文件中在函數(shù)定義前做一樣的修改即可):
            需要注意的就是調(diào)用修飾符只能用在函數(shù)和成員函數(shù)的前面,而且要在返回值類型之后的位置。
            // 下列 ifdef 塊是創(chuàng)建使從 DLL 導(dǎo)出更簡單的
            // 宏的標(biāo)準(zhǔn)方法。此 DLL 中的所有文件都是用命令行上定義的 PUREDLL_EXPORTS
            // 符號編譯的。在使用此 DLL 的
            // 任何其他項目上不應(yīng)定義此符號。這樣,源文件中包含此文件的任何其他項目都會將
            // PUREDLL_API 函數(shù)視為是從 DLL 導(dǎo)入的,而此 DLL 則將用此宏定義的
            // 符號視為是被導(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對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)生的修飾符相同,其實產(chǎn)生的修飾符不是這兩種的任何一種,而是__thiscall的修飾符,從PureDll.lib的后面括號中可以看出來,而且VC9.0中在構(gòu)造函數(shù)前面使用__cdecl會直接產(chǎn)生編譯時警告c4166,如下:
            編譯器警告(等級 1)C4166
            構(gòu)造函數(shù)
            /析構(gòu)函數(shù)的非法調(diào)用約定 

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

            再對照第一組中setValue函數(shù)在PureDll.lib中產(chǎn)生的修飾符,可以知道類成員函數(shù)默認(rèn)使用__thiscall修飾符,即使編譯器選項中選擇了__cdecl,也就是說構(gòu)造函數(shù)和析構(gòu)函數(shù)必須使用當(dāng)前平臺默認(rèn)的調(diào)用方式----__thiscall,其它的成員函數(shù)可以通過在函數(shù)名前(聲明和定義)強(qiáng)制加上指定的調(diào)用方式即可,編譯器選項中的調(diào)用方式不行(這里指定的方式只是對非成員函數(shù)有效的,成員函數(shù)會默認(rèn)使用__thiscall)。
            其實__thiscall和__stdcall差別不大,都是被調(diào)用者控制棧的初始和清理,只不過前者的this指針放在寄存器中,而后者的放在棧里。所以對于成員函數(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.對應(yīng)上面的extern "C",下面是cpp(去掉extern "C")下對應(yīng)上面的修飾符:
            (1)__cdecl作用下:
            PureApp.exe對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對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ǔ)充一個強(qiáng)制指定__cdecl的setValue的修飾符:
                              ?setValue@CPureDll@@QAAXH@Z (publicvoid __cdecl CPureDll::setValue(int))

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

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


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


            久久国产成人精品国产成人亚洲| 精品熟女少妇AV免费久久| 久久综合狠狠综合久久激情 | 欧美亚洲国产精品久久蜜芽| 久久午夜综合久久| 亚洲国产精品无码久久98| 丰满少妇人妻久久久久久| 国产精品成人精品久久久| 久久综合偷偷噜噜噜色| 国产亚洲综合久久系列| 久久亚洲精品成人无码网站| 久久亚洲春色中文字幕久久久| 国内精品久久久久久麻豆 | 久久99这里只有精品国产| 99久久精品国产麻豆| 国内精品人妻无码久久久影院导航| A狠狠久久蜜臀婷色中文网| 91麻豆国产精品91久久久| 91性高湖久久久久| 色噜噜狠狠先锋影音久久| 久久国产色AV免费观看| 狠狠色丁香久久婷婷综合| 伊色综合久久之综合久久| 国产精品成人久久久久三级午夜电影 | 日韩欧美亚洲国产精品字幕久久久 | 久久久SS麻豆欧美国产日韩| 久久99久久无码毛片一区二区| 99久久精品国内| avtt天堂网久久精品| 9久久9久久精品| 99re久久精品国产首页2020| 午夜天堂av天堂久久久| 国产69精品久久久久久人妻精品| 久久伊人色| 国产精品久久久久久久久软件| 久久成人18免费网站| 久久精品中文字幕一区| 久久综合久久伊人| 国内精品综合久久久40p| 色综合久久无码五十路人妻| 久久精品国产久精国产思思|