(1) _stdcall调用

  _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。
  WIN32 Api都采用_stdcall调用方式,这样的宏定义说明了问题:

  #define WINAPI _stdcall

  按C编译方式,_stdcall调用约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数,形如。

(2) _cdecl调用
  _cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式,传送参数的内存栈由调用者维护。_cedcl约定的函数只能被C/C++调用,每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。

  由于_cdecl调用方式的参数内存栈由调用者维护,所以变长参数的函数能(也只能)使用这种调用约定。关于C/C++中变长参数(…)的问题,笔者将另文详述。

  由于Visual C++默认采用_cdecl 调用方式,所以VC中中调用DLL时,用户应使用_stdcall调用约定。
  按C编译方式,_cdecl调用约定仅在输出函数名前面加下划线,形如_functionname。

(3) _fastcall调用
  _fastcall调用较快,它通过CPU内部寄存器传递参数。

  按C编译方式,_fastcall调用约定在输出函数名前面加“@”符号,后面加“@”符号和参数的字节数,形如@functionname@number。

几乎我们写的每一个WINDOWS API函数都是__stdcall类型的,为什么??
     首先,我们谈一下两者之间的区别:
       WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数
调用完成后,栈需要清除,这里就是问题的关键,如何清除??
       如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲
就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同
,那么调用者能否正常的完成清除工作呢?答案是不能。
       如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨
(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。
       那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变
的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行
,因此,这种情况我们只能使用_cdecl。
       到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字.

_stdcall,_cdecl区别的更多相关文章

  1. __stdcall,__cdecl,__fastcall,_stdcall,_cdecl,_fastcall 区别简介[转]

    今天写线程函数时,发现msdn中对ThreadProc的定义有要求: DWORD WINAPI ThreadProc(LPVOID lpParameter);   不解为什么要用WINAPI宏定义,查 ...

  2. 转:函数调用的区别:_cdecl以及_stdcall

    函数调用的几个概念:_stdcall,_cdecl.... 1._stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈.VC将 ...

  3. linux内核调试指南

    linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级调试 ***第一部分:基础知识*** 总纲:内核世界的陷阱 源码阅读的陷阱 代码调试的陷阱 原理理解的陷阱 ...

  4. Linux Kernel - Debug Guide (Linux内核调试指南 )

    http://blog.csdn.net/blizmax6/article/details/6747601 linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级 ...

  5. 调用 Dll 中的函数时,出现栈(STACK)的清除问题 -> 故障模块名称: StackHash_0a9e

    在一个名为 test.dll 文件中,有一个 Max() 函数的定义是: #ifdef BUILD_DLL #define DLL_EXPORT __declspec(dllexport) __std ...

  6. 可变参数以及stdcall

    void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2); #define EV_CHECK_FMT(a,b) __attribute__((f ...

  7. .NET本质论 方法

    方法和JIT编译 CLR只执行本机的机器代码.如果一个方法体由CIL组成,那么它就必须在调用之前被转换为本机的机器码(将MSIL编译为本机代码,运行库提供了两种方式.一种就是在安装与部署时的预编译(由 ...

  8. __stdcall,__cdecl,_cdecl,_stdcall,。__fastcall,_fastcall 区别简介

    1. 今天写线程函数时,发现msdn中对ThreadProc的定义有要求:DWORD WINAPI ThreadProc(LPVOID lpParameter); 不解为什么要用WINAPI宏定义,查 ...

  9. 函数调用的区别:_cdecl以及_stdcall

    一.概念1)_stdcall调用   _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,由调用者完成压栈操作,被调函数自身在返回前清空堆栈.   WIN32 Api都采用_ ...

随机推荐

  1. 一行python代码实现树结构

    树结构是一种抽象数据类型,在计算机科学领域有着非常广泛的应用.一颗树可以简单的表示为根, 左子树, 右子树. 而左子树和右子树又可以有自己的子树.这似乎是一种比较复杂的数据结构,那么真的能像我们在标题 ...

  2. Asp.Net MVC<三> : ASP.NET MVC 基本原理及项目创建

    MVC之前的那点事儿系列 解读ASP.NET 5 & MVC6系列 MVC模拟(摘自ASP.NET MVC5框架揭秘) Asp.net中,通过HttpModule的形式定义拦截器,也就是路由表 ...

  3. Ubuntu(基于Ubuntu)中常用的apt和dpkt命令

    apt-get sudo apt-get install package 安装包   sudo apt-get -f install 修复安装”-f = ——fix-missing”   sudo a ...

  4. Nginx简易配置文件(二)(反向代理)

    user nobody nobody; worker_processes 4; error_log logs/error.log; pid logs/nginx.pid; events { use e ...

  5. 将DataTable中的数据导出到Excel

    public static void Export(System.Data.DataTable dt,NPOI.HSSF.UserModel.HSSFWorkbook workbook,string ...

  6. HTML5学习总结-番外05 响应式布局

    1. 响应式布局 响应式布局是2015年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端,而不是为每个终端做一个特定的版本.这个概念是为解决移动互联网浏览而诞生的.其目的是为用户提欧共更加 ...

  7. Publishing failed with multiple errors 异常

    Publishing failed with multiple errors 在使用eclipse发布项目时不能自动生成class文件,且无法启动调试的Tomcat服务.启动过程提示 以上 异常 解决 ...

  8. oracle---日期等plsql

    日期/时间 相关查询 1.获取当前月份的第一天 运行这个命令能快速返回当前月份的第一天.你可以用任何的日期值替换 "SYSDATE"来指定查询的日期. SELECT TRUNC ( ...

  9. oracle---jdbc--laobai

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...

  10. Windows10环境搭建Elasticsearch+Kibana+Marvel

    环境: Windows10企业版X64 Elasticsearch-2.4.1 Kibana-4.6.1 Marvel-2.0+ 步骤: 安装Elasticsearch:官网下载Elasticsear ...