日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

__stdcall和__cdecl的区别

發(fā)布時間:2024/4/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 __stdcall和__cdecl的区别 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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

Windows上

windows上不管是C還是C++,默認(rèn)使用的都是__stdcall方式。

不論__stdcall還是__cdecl函數(shù)參數(shù)都是從可向左入棧的,并且由調(diào)用者完成入棧操作。對于__stdcall方式被調(diào)用者自身在函數(shù)返回前清空堆棧;而__cdecl則由調(diào)用者維護(hù)內(nèi)存堆棧,所以調(diào)用者函數(shù)生成的匯編代碼比前一種方式長。

由__cdecl約定的函數(shù)只能被C/C++調(diào)用。

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

C語言

__stdcall方式:_FuncName@sizeofParameters

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

__cdecl方式:_FuncName

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

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

C++語言

不管__cdecl,__fastcall還是__stdcall調(diào)用方式,函數(shù)修飾都是以一個“?”開始,后面緊跟函數(shù)的名字,再后面是參數(shù)表的開始標(biāo)識和按照參數(shù)類型代號拼出的參數(shù)表。對于__stdcall方式,參數(shù)表的開始標(biāo)識是“@@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類型的指針

如果相同類型的指針連續(xù)出現(xiàn),以“0”代替,一個“0”代表一次重復(fù);

U表示結(jié)構(gòu)類型,通常后跟結(jié)構(gòu)體的類型名,用“@@”表示結(jié)構(gòu)類型名的結(jié)束;

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

參數(shù)表后以“@Z”標(biāo)識整個名字的結(jié)束,如果該函數(shù)無參數(shù),則以“Z”標(biāo)識結(jié)束。

舉例:

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

C++中調(diào)用由C編譯器生成的函數(shù)

extern "C" {

long func(int a);

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

}

extern "C" {

#include<string.h>

}

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

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

通常應(yīng)該這樣聲明頭文件:

#ifdef _cplusplus extern?"C"?{ #endif long?MakeFun(long?lFun); #ifdef _cplusplus } #endif

?有兩種方式可以檢查你的程序中的函數(shù)的名字修飾:使用編譯輸出列表或使用Dumpbin工具。使用/FAc,/FAs或/FAcs命令行參數(shù)可以讓編譯器輸出函數(shù)或變量名字列表。使用dumpbin.exe /SYMBOLS命令也可以獲得obj文件或lib文件中的函數(shù)或變量名字列表。此外,還可以使用 undname.exe 將修飾名轉(zhuǎn)換為未修飾形式。

Linux上

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

int?__attribute__((cdecl)) test();

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

__stdcall和__cdecl沒有區(qū)別,有區(qū)別的是編程語言。

C++語言

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

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

C語言

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

char test(); ?----- ? ?test

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

?

附:

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

查看二進(jìn)制文件:hexdump -C biFile

編輯二進(jìn)制文件:hexedit biFile

總結(jié)

以上是生活随笔為你收集整理的__stdcall和__cdecl的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。