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

            把握命運,追逐夢想

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

            統計

            留言簿(1)

            閱讀排行榜

            評論排行榜

            __cdecl、__stdcall、__fastcall

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

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

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

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

            C 和C++ 對應不同的調用約定,產生的修飾符也各不相同,對于函數test(void)如下:
            調用約定 extern "C" 或 .c 文件 .cpp、.cxx 或 /TP

            C 命名約定 (__cdecl)

            _test

            ?test@@ZAXXZ

            Fastcall 命名約定 (__fastcall)

            @test@0

            ?test@@YIXXZ

            標準調用命名約定 (__stdcall)

            _test@0

            ?test@@YGXXZ

            第二列,也就是C風格的情況下,@后面的數字表述所有參數的字節數之和。
            第三列,也就是CPP風格的情況下,修飾符有些復雜,以后補充吧。

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

                              
            ??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的導出修飾符如下:
                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作用下(調用方式的改變在函數聲明和定義之前都要使用,下面先是發生改變的頭文件,cpp文件中在函數定義前做一樣的修改即可):
            需要注意的就是調用修飾符只能用在函數和成員函數的前面,而且要在返回值類型之后的位置。
            // 下列 ifdef 塊是創建使從 DLL 導出更簡單的
            // 宏的標準方法。此 DLL 中的所有文件都是用命令行上定義的 PUREDLL_EXPORTS
            // 符號編譯的。在使用此 DLL 的
            // 任何其他項目上不應定義此符號。這樣,源文件中包含此文件的任何其他項目都會將
            // PUREDLL_API 函數視為是從 DLL 導入的,而此 DLL 則將用此宏定義的
            // 符號視為是被導出的。

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

                
            // 此類是從 PureDll.dll 導出的
                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的導入修飾符如下:
               5 g_pureDll
               
            1 ??1CPureDll@@QAE@XZ
               
            4 _fnPureDll@0
               
            3 ?setValue@CPureDll@@QAGXH@Z
               
            0 ??0CPureDll@@QAE@H@Z
               
            6 nPureDll
            PureDll.lib的導出修飾符如下:
                              ??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的導出修飾符如下:
                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

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

            構造函數和析構函數不能有非平臺默認的調用約定(顯式指定 __clrcall 時除外)。

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

            2.對應上面的extern "C",下面是cpp(去掉extern "C")下對應上面的修飾符:
            (1)__cdecl作用下:
            PureApp.exe對PureDll.dll的導入修飾符如下:
                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的導出修飾符如下:
                              ??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的導出修飾符如下:
                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的導入修飾符如下:
               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的導出修飾符如下:
                              ??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的導出修飾符如下:
                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)

            補充一個強制指定__cdecl的setValue的修飾符:
                              ?setValue@CPureDll@@QAAXH@Z (publicvoid __cdecl CPureDll::setValue(int))

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

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

            色欲综合久久躁天天躁蜜桃| 蜜桃麻豆www久久| 看全色黄大色大片免费久久久| 中文字幕精品久久| 久久99国产精品二区不卡| 国内精品伊人久久久久影院对白| 伊人久久大香线蕉精品不卡 | 草草久久久无码国产专区| 久久精品一区二区影院| av色综合久久天堂av色综合在| 丁香狠狠色婷婷久久综合| 欧美激情精品久久久久久久九九九| 无码精品久久久天天影视| 久久国产美女免费观看精品| 亚洲午夜无码久久久久| 久久性精品| 欧美一区二区精品久久| 亚洲色欲久久久综合网| 欧美色综合久久久久久| 久久亚洲国产午夜精品理论片| 亚洲午夜久久久久妓女影院| 人妻无码精品久久亚瑟影视| 99久久免费国产特黄| 色综合久久久久无码专区| 无码精品久久一区二区三区| 久久不见久久见免费影院www日本| 久久久女人与动物群交毛片| 狠狠色狠狠色综合久久| 热久久视久久精品18| 亚洲人成电影网站久久| 日本欧美国产精品第一页久久| 日韩一区二区久久久久久| 狠狠色丁香婷婷久久综合不卡| 亚洲国产精品无码久久久秋霞2 | 国产欧美久久久精品影院| 亚洲国产成人精品久久久国产成人一区二区三区综 | 人人妻久久人人澡人人爽人人精品| 青青青青久久精品国产h久久精品五福影院1421 | 久久人人爽人人爽人人片AV不| 久久91精品国产91| 中文字幕无码免费久久|