当前位置:首页 » 编程语言 » c语言stdcall
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

c语言stdcall

发布时间: 2022-07-14 21:07:28

‘壹’ 调用规范stdcall和c语言的区别

在函数参数处理上不同_stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。WIN32Api都采用_stdcall调用方式_cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式,传送参数的内存栈由调用者维护。_cedcl约定的函数只能被C/C++调用,每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。由于_cdecl调用方式的参数内存栈由调用者维护,所以变长参数的函数能(也只能)使用这种调用约定。相应的代码实例见网盘:附:几乎我们写的每一个WINDOWSAPI函数都是__stdcall类型的,为什么??首先,我们谈一下两者之间的区别:WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除??如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字

‘贰’ 关于c语言的头文件问题

如果定义了__STDC__,就说明这个编译器遵循标准C。所以把_Cdecl定义为空字符串,也就是相当于把所有的_Cdecl删除了。
如果没有定义__STDC__,就是明这个编译器不遵循标准C。那么把_Cdecl定义为 cdecl。

其实cdecl可能也是一个宏,当编译器支持一个叫“调用约定”的扩展时,cdecl被定义成这种扩展的语法。
之所以有这段条件编译是因为标准C不支持“调用约定”。

‘叁’ 如何运用c++里的“__stdcall”

1、__stdcall调用类型:该调用只是通过堆栈来push和pop参数。push参数时,顺序是从右到左。

2、“_stdcall”的作用 :在C/C++中函数默认Calling Conventions(调用约定)是:参数由右向左压入栈,由调用者清空栈。

3、在FORTRAN、PASCAL、VisualBASIC等语言中,函数的Calling Conventions是:参数由右向左压入栈,由被调函数清空栈。

4、__cdecl调用类型:这是C的调用规则。对于所有非C++成员函数或未标有__stdcall或__fastcall的函数来说,这是默认调用规则。

5、__fastcall调用类型:从字面意思可知,这是一种快速调用。因为CPU的寄存器会被使用来存放函数参数列表中的头几个参数。而剩下参数将被从右至左地推倒堆栈上。被调用函数将从 寄存器和堆栈获得函数参数。

6、在x86中,ECX和EDX一般被用来存放开始的参数。在.NET中,为了性能上的快速,就是使用ecx和edx来实现 __fastcall的。

‘肆’ c语言函数调用规则

_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。

_cdecl 按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)是C和C++程序的默认调用约定。__cdecl调用约定仅在输出函数名前加上一个下划线前缀,格式为_functionname。

_fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈。__fastcall调用约定在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,格式为@functionname@number。

‘伍’ C语言函数调用的三种方式并分别举一例。

1、值传递,创建变量x和y,x的值等于a的值,y的值等于b的值

void Exchg1(int x, int y)

{

int tmp;

tmp=x;

x=y;

y=tmp;

printf(“x=%d,y=%d/n”,x,y)

}

void main()

{

int a=4,b=6;

Exchg1 (a,b) ;

printf(“a=%d,b=%d/n”,a,b)

}

2、地址传递,相当于建立了px和py两个指向整型的指针,其值分别为a和b的地址

Exchg2(int *px, int *py)

{

int tmp=*px;

*px=*py;

*py=tmp;

print(“*px=%d,*py=%d/n”,*px,*py);

}

main()

{

int a=4;

int b=6;

Exchg2(&a,&b);

Print(“a=%d,b=%d/n”, a, b);

}

3、引用传递,x和y直接引用a和b,对a和b操作,相当于给a、b起了别名x、y

Exchg2(int &x, int &y)

{

int tmp=x;

x=y;

y=tmp;

print(“x=%d,y=%d/n”,x,y);

}

main()

{

int a=4;

int b=6;

Exchg2(a,b);

Print(“a=%d,b=%d/n”, a, b);

}

(5)c语言stdcall扩展阅读:

printf用法:

printf()函数的调用格式为:printf("<格式化字符串>",<参量表>)。

其中格式化字符串包括两部分内容:一部分是正常字符,这些字符将按原样输出;另一部分是格式化规定字符,以"%"开始,后跟一个或几个规定字符,用来确定输出内容格式。

参量表是需要输出的一系列参数,其个数必须与格式化字符串所说明的输出参数个数一样多,各参数之间用","分开,且顺序一一对应,否则将会出现意想不到的错误。

比如:

int a=1234;

printf("a=%d ",a);

输出结果为a=1234。

‘陆’ C语言的回调函数

callback Function
回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。
理解回调函数!

程序在调用一个函数(function)时(通常指api).相当于程序(program)呼叫(Call)了一个函数(function)关系表示如下:
call(调用)
program --------------------→ dll

程序在调用一个函数时,将自己的函数的地址作为参数传递给程序调用的函数时(那么这个自己的函数称回调函数).需要回调函数的 DLL 函数往往是一些必须重复执行某些操作的函数.关系表示如下:

call(调用)
program --------------------→ dll
↑ ¦
¦_______________________________¦
callback(回调)

当你调用的函数在传递返回值给回调函数时,你就可以利用回调函数来处理或完成一定的操作。至于如何定义自己的回调函数,跟具体使用的API函数有关,很多不同类别的回调函数有各种各样的参数,有关这些参数的描述一般在帮助中有说明回调函数的参数和返回值等.其实简单说回调函数就是你所写的函数满足一定条件后,被DLL调用!

也有这样的说法(比较容易理解):
回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事:
1. 声明;
2. 定义;
3. 设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于DLL调用。

‘柒’ __cdecl __stdcall 是什么意思

__cdecl 是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
_stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。

‘捌’ c语言几种调用分别是什么为什么他们速度不一样

_cdecl 是C Declaration的缩写,表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。

_stdcall 是Standard Call的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retn X,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。

PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与前两者相反。返回时的清栈方式忘记了。。。

_fastcall 是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。

_thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。

_fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。

确实是复制的!希望对你有所帮助!只是忘记了原出处了!