__declspec,__cdecl,__stdcall区别和作用
_cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的 顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要注意了,只有用相同的方法才能够调用成功.另外, 像printf这样接受可变个数参数的函数只有用cdecl才能够实现.
__declspec主要是用于说明DLL的引出函数的,在某些情况下用__declspec(dllexport)在DLL中生命引出函数,比用传统的
DEF文件方便一些.在普通程序中也可以用__declspec(dllimport)说明函数是位于另一个DLL中的导出函数.
int WINAPI MessageBoxA(HWND,LPCSTR,LPSTR,UINT);
而WINAPI实际上就是__stdcall.
大多数API都采用__stdcall调用规范,这是因为几乎所有的语言都支持__stdcall调用.相比之下,__cdecl只有在C语言中才能用.
但是__cdecl调用有一个特点,就是能够实现可变参数的函数调用,比如printf,这用__stdcall调用是不可能的.
__fastcall这种调用规范比较少见,但是在Borland C++ Builder中比较多的采用了这种调用方式.
如果有共享代码的需要,比如写DLL,推荐的方法是用__stdcall调用,因为这样适用范围最广.如果是C++语言写的代码供Delphi这样的语言
调用就必须声明为__stdcall,因为Pascal不支持cdecl调用(或许Delphi的最新版本能够支持也说不定,这个我不太清楚).在其他一
些地方,比如写COM组件,几乎都用的是stdcall调用.在VC或Delphi或C++Builder里面都可以从项目设置中更改默认的函数调用规
范,当然你也可以在函数声明的时候加入__stdcall,__cdecl,__fastcall关键字来明确的指示本函数用哪种调用规范.
__declspec一般都是用来声明DLL中的导出函数.这个关键字也有一些其他的用法,不过非常罕见.
允许同一个名字(具有不同的参数类型或者是不同的作用域)有多个用法,而不会打破现有的基于C的链接器。这项技术通常被称为名称改编(Name
Mangling)或者名称修饰(Name Decoration)。许多C++编译器厂商选择了自己的名称修饰方案。
调用约定用来处理决定函数参数传送时入栈和出栈的顺序(由调用者还是被调用者把参数弹出栈),以及编译器用来识别函数名称的名称修饰约定等问题。在Microsoft VC++ 6.0中定义了下面几种调用约定,我们将结合汇编语言来一一分析它们:
来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该
调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。
API函数。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知
道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。__stdcall可以写成_stdcall。
大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈。
__fastcall可以写成_fastcall。
译环境的Setting...->C/C++->Code
Generation项选择。它们对应的命令行参数分别为/Gd、/Gz和/Gr。缺省状态为/Gd,即__cdecl。当加在输出函数前的关键字与编译
环境中的选择不同时,直接加在输出函数前的关键字有效。
用,没有相应的关键字,因此不能被程序员指定。采用thiscall约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,只
是另外通过ECX寄存器传送一个额外的参数:this指针。
存器中的值,退出函数时则产生代码恢复这些寄存器的内容。对于定义了naked属性的函数,编译器不会自动产生这样的代码,需要你手工使用内嵌汇编来控制
函数实现中的堆栈管理。由于naked属性并不是类型修饰符,故必须和__declspec共同使用。下面的这段代码定义了一个使用了naked属性的函
数及其实现:
C或C++函数在内部(编译和链接)通过修饰名(Decoration
Name)识别。函数的修饰名是编译器在编译函数定义或者原型时生成的字符串。编译器在创建.obj文件时对函数名称进行修饰。有些情况下使用函数的修饰
名是必要的,如在模块定义文件里头指定输出C++重载函数、构造函数、析构函数,又如在汇编代码里调用C或C++函数等。
参数的字节数,格式为@functionname@number。例如:函数int __fastcall Add(int a, int
b),输出后为:@Add@8。
__declspec,__cdecl,__stdcall区别和作用的更多相关文章
- __declspec,__cdecl,__stdcall都是什么意思?有什么作用?
__cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要 ...
- 函数调用方式--__thiscall调用方式和__cdecl,__stdcall有什么区别
函数调用方式--__thiscall调用方式和__cdecl,__stdcall有什么区别 首先,__thiscall是关于类的一种调用方式,它与其他调用方式的最大区别是: __thiscall ...
- 浅析匿名函数、lambda表达式、闭包(closure)区别与作用
浅析匿名函数.lambda表达式.闭包(closure)区别与作用 所有的主流编程语言都对函数式编程有支持,比如c++11.python和java中有lambda表达式.lua和JavaScript中 ...
- maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令
maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令 在日常的工作中由于各种原因,会出现这样一种情况,某些项目并没有打包至mvnrepository. ...
- 深入解析Oracle 10g中SGA_MAX_SIZE和SGA_TARGET参数的区别和作用
原文链接:http://m.blog.csdn.net/blog/aaron8219/40037005 SGA_MAX_SIZE是从9i以来就有的作为设置SGA大小的一个参数,而SGA_TARGET则 ...
- jsp中的contentType与pageEncoding的区别和作用
jsp中的contentType与pageEncoding的区别和作用 <%@ page contentType="text/html; charset=utf-8" p ...
- Python 实例方法、类方法、静态方法的区别与作用
Python中至少有三种比较常见的方法类型,即实例方法,类方法.静态方法.它们是如何定义的呢?如何调用的呢?它们又有何区别和作用呢?且看下文. 首先,这三种方法都定义在类中.下面我先简单说一下怎么定义 ...
- [转] <context-param>与<init-param>的区别与作用
看到一篇关于web.xm文件中标签的讲解,顺带还阐述了容器的工作流程,因此转载此,以供参考,原文地址:与的区别与作用 <context-param>的作用: web.xml的配置中< ...
- nginx和uwsgi的区别和作用
Django+uwsgi+nginx nginx和uwsgi的区别和作用: 1, nginx是对外的服务器,外部浏览器通过url访问nginx, uwsgi是对内的服务器,主要用来处理动态请求. 2, ...
随机推荐
- hql查询语句 内存中的情况,fetch迫切查询关键字
Classes.java package cn.itcast.hiberate.sh.domain; import java.io.Serializable; import java.util.Set ...
- Android 中像素px和dp的转化
在Android的布局文件中,往往使用dp作为控件的宽度和高度尺寸,但是在Java代码中,调用getWidth()方法获得的尺寸单位却是像素px,这两个单位有明显的区别:dp和屏幕的密度有关,而px与 ...
- Delphi 关闭MDI子窗口
需要在子窗口的onClose事件中吧Action = caFree; 就可以了. procedure Tfrm_aa.FormClose(Sender: TObject; var Action: TC ...
- Linux 文件的几种类型
文件的几种类型: 1.普通文件 普通文件就是一般意义上的文件,它们作为数据存储在系统磁盘中,可以随机访问文件的内容.Linux系统中的文件是面向字节的,文 件的内容以字节为单位进行存储与访问 ...
- 五种情况会导致Session 丢失
1.Session到期自定丢失.2.当修改web.config 系统会重启 SESSION 会丢失.3.Bin目录有变化时候系统会重启 SESSION会丢失 (这里变化指的是,创建新文件.修改文件名 ...
- 原创 | 《地狱边境》登顶50国iOS下载榜,恐怖游戏或是独立开发者突破口(转)
文/手游那点事 Jagger 与大厂强IP称霸的App Store畅销榜相比,付费榜一向是独立游戏的温床.高质量的独立游戏并不需要在推广营销中投入太多成本,依靠过硬的品质和口碑在付费榜中缓缓上升造就高 ...
- 数往知来 三层架构 <十四>
三层架构_1 一.三层 就是把程序的各个部分都分离,尽量的底耦合,做到分工明确.责任明确 第一层:Dal 数据访问层 第二层 :Bll 业务逻辑判断层 第三层: UI 界面显示层 比如说数据 ...
- MySQL安装(图文详解)
下面的是MySQL安装的图解,用的可执行文件安装的,详细说明了一下!打开下载的mysql安装文件mysql-5.0.27-win32.zip,双击解压缩,运行“setup.exe”,出现如下界面 my ...
- 写好Hive 程序的五个提示
转自http://www.alidata.org/archives/622 使用Hive可以高效而又快速地编写复杂的MapReduce查询逻辑.但是某些情况下,因为不熟悉数据特性,或没有遵循Hive的 ...
- Delphi中BitBlt函数实现屏幕对象抓图
uses WinTypes, WinProcs, Forms, Controls, Classes, Graphics; function CaptureScreenRect( ARect: TRec ...