DWORD WINAPI?stdcall?
2021-03-13 00:36
标签:under 语言 fun 说明 fas 开发平台 define 如何 client 在网络编程实验2_(4)基于流式套接字的服务器程序设计中,创建了以下这个函数: DWORD WINAPI ClientThread(LPVOID lpParameter) 以前我只学过类似: int swap(int x,int y) 这样的函数,而这个函数看起来就很诡异,如何理解这个函数呢? DWORD是数据类型,在这里是返回值,返回32位数据。 在visual studio中WINAPI转到定义可以看到: #define WINAPI __stdcall 也就是说WINAPI是一个宏,所代表的符号是__stdcall。 WINAPI是函数调用形式,windows API函数采用__stdcall标准调用约定,即由被调用函数来清理栈中的参数,这种方式是不能实现可变参数的。 __stdcall是函数调用约定的一种,函数调用约定主要约束了两件事: 1.参数传递顺序 2.调用堆栈由谁(调用函数或被调用函数)清理 常见的函数调用约定:stdcall cdecl fastcall thiscall naked call __stdcall表示 1.参数从右向左压入堆栈 2.函数被调用者修改堆栈 3.函数名(在编译器这个层次)自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸 在win32应用程序里,宏APIENTRY,WINAPI,都表示_stdcall,非常常见。 摘自: 在C语言中,假设我们有这样的一个函数:int function(int a,int b) 为了深刻理解__stdcall,我查找了一些资料,参考链接如下: (这位老哥讲的很全面,但是格式有点乱。于是我稍微调整了一下格式) __stdcall、__cdecl和__fastcall是三种函数调用协议,函数调用协议会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则等。 调用协议常用场合 __stdcall:Windows API默认的函数调用协议。 __cdecl:C/C++默认的函数调用协议。 __fastcall:适用于对性能要求较高的场合 函数参数入栈方式 __stdcall:函数参数由右向左入栈。 __cdecl:函数参数由右向左入栈。 __fastcall:从左开始不大于4字节的参数放入CPU的ECX和EDX寄存器,其余参数从右向左入栈。 栈内数据清除方式 __stdcall:函数调用结束后由被调用函数清除栈内数据。 __cdecl:函数调用结束后由函数调用者清除栈内数据。 __fastcall:函数调用结束后由被调用函数清除栈内数据。 (1)不同编译器设定的栈结构不尽相同,跨开发平台时由函数调用者清除栈内数据不可行。 (2)某些函数的参数是可变的,如printf函数,这样的函数只能由函数调用者清除栈内数据。 (3)由调用者清除栈内数据时,每次调用都包含清除栈内数据的代码,故可执行文件较大。 C语言编译器函数名称修饰规则 __stdcall:编译后,函数名被修饰为“_functionname@number”。 __cdecl:编译后,函数名被修饰为“_functionname”。 __fastcall:编译后,函数名给修饰为“@functionname@nmuber”。 注:“functionname”为函数名,“number”为参数字节数。 注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。 C++语言编译器函数名称修饰规则 __stdcall:编译后,函数名被修饰为“?functionname@@YG******@Z”。 __cdecl:编译后,函数名被修饰为“?functionname@@YA******@Z”。 __fastcall:编译后,函数名被修饰为“?functionname@@YI******@Z” 注:“******”为函数返回值类型和参数类型表。 注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。 C语言和C++语言间如果不进行特殊处理,也无法实现函数的互相调用。 DWORD WINAPI?stdcall? 标签:under 语言 fun 说明 fas 开发平台 define 如何 client 原文地址:https://www.cnblogs.com/cyx-b/p/12555128.html
调用时只要用result = function(1,2)这样的方式就可以使用这个函数。但是,当高级语言被编译成计算机可以识别的机器码时,有一个问题就凸现出来:在CPU中,计算机没有办法知道一个函数调用需要多少个、什么样的参数,也没有硬件可以保存这些参数。也就是说,计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数调用者和函数本身来协调。为此,计算机提供了一种被称为栈的数据结构来支持参数传递。
栈是一种先进后出的数据结构,栈有一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用的数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入数据,这个操作被称为压栈(Push),压栈以后,栈顶自动变成新加入数据项的位置,栈顶指针也随之修改。用户也可以从堆栈中取走栈顶,称为弹出栈(pop),弹出栈后,栈顶下的一个元素变成栈顶,栈顶指针随之修改。函数调用时,调用者依次把参数压栈,然后调用函数,函数被调用以后,在堆栈中取得数据,并进行计算。函数计算结束以后,或者调用者、或者函数本身修改栈,使堆栈恢复原装。
在参数传递中,有两个很重要的问题必须得到明确说明:
当参数个数多于一个时,按照什么顺序把参数压入堆栈函数调用后,由谁来把堆栈恢复原装。在高级语言中,通过函数调用约定来说明这两个问题。常见的调用约定有:
stdcall,cdecl,fastcall,thiscall,naked call
C++知识回顾之__stdcall、__cdcel和__fastcall三者的区别