__stdcall和__cdecl的區別


__stdcall和__cdecl是兩種函數名字修飾。(注意是連續的兩個下划線)

Windows上

windows上不管是C還是C++,默認使用的都是__stdcall方式。

不論__stdcall還是__cdecl函數參數都是從可向左入棧的,並且由調用者完成入棧操作。對於__stdcall方式被調用者自身在函數返回前清空堆棧;而__cdecl則由調用者維護內存堆棧,所以調用者函數生成的匯編代碼比前一種方式長。

由__cdecl約定的函數只能被C/C++調用。

Windows上使用dumpbin工具查看函數名字修飾。

C語言

__stdcall方式:_FuncName@sizeofParameters

例如:int __stdcall test(int a,double b)編譯之后完整的函數名為_test@12

__cdecl方式:_FuncName

例如:int __stdcall test(int a,double b)編譯之后完整的函數名為_test

由於C++允許重載函數,所以函數的名字修飾就不能像C這么簡單,C++中的函數名字修飾應該包含返回類型,各參數類型等信息,如果是類成員函數,還應該包含類名、訪問級別、是否為const函數等等信息。

C++語言

不管__cdecl,__fastcall還是__stdcall調用方式,函數修飾都是以一個“?”開始,后面緊跟函數的名字,再后面是參數表的開始標識和按照參數類型代號拼出的參數表。對於__stdcall方式,參數表的開始標識是“@@YG”,對於__cdecl方式則是“@@YA”。

X--void    
D--char    
E--unsigned char    
F--short    
H--int    
I--unsigned int    
J--long    
K--unsigned long(DWORD) 
M--float    
N--double    
_N--bool
U--struct
PA--指針

PB--const類型的指針

如果相同類型的指針連續出現,以“0”代替,一個“0”代表一次重復;

U表示結構類型,通常后跟結構體的類型名,用“@@”表示結構類型名的結束;

函數參數表的第一項實際上是表示函數的返回值類型;

參數表后以“@Z”標識整個名字的結束,如果該函數無參數,則以“Z”標識結束。

舉例:

int Function1 (char *var1,unsigned long);其函數修飾名為“?Function1@@YGHPADK@Z”
void Function2();其函數修飾名則為“?Function2@@YGXXZ” 

C++中調用由C編譯器生成的函數

extern "C" {

long func(int a);

char* strcat(char*,const char*);

}

extern "C" {

#include<string.h>

}

要想在編譯階段就知道使用的編譯器類型,可以使用:

#ifdef __cplusplus
cout<<"C++";
#else
printf("C");
#endif

通常應該這樣聲明頭文件:

#ifdef _cplusplus
extern "C" {
#endif

long MakeFun(long lFun);

#ifdef _cplusplus
}
#endif

Linux上

Linux上使用__stdcall和__cdecl的方式比較麻煩一些。

int __attribute__((cdecl)) test();

Linux上使用nm工具查看函數名字修飾。

__stdcall和__cdecl沒有區別,有區別的是編程語言。

C++語言

char test();  -----    _Z4testv            _Z表示C++,4代表函數名有4個字節,test是函數名,v代表參數為空

double func(unsigned int a,double *b,char c);   -----      _Z4funcjPdc     j代表int,Pd代表double型指針,c代表char

C語言

只是簡單一個函數名,沒有其他修飾信息。

char test();  -----    test

double func(unsigned int a,double *b,char c);   -----      func

 

附:

Linux上的反匯編工具:objdump  -x  exefile

查看二進制文件:hexdump -C biFile

編輯二進制文件:hexedit biFile


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM