c/c++ stdcall cdel fastcall等函数调用约定说明
调用约定(Calling Conventions)是编程中定义函数如何接收参数、返回值以及如何管理堆栈的协议。主要的调用约定包括 __cdecl
、__stdcall
、__fastcall
和 __thiscall
等。下面将详细介绍这些调用约定的特点及其适用场景。
1. __cdecl
调用约定
- 定义:
__cdecl
是 C 语言的默认调用约定,适用于支持可变数量参数的函数。 - 参数传递:
- 参数从右到左压入堆栈。
- 堆栈清理:
- 由调用者负责清理堆栈。这意味着在函数调用后,调用者需要调整堆栈指针以移除参数。
- 返回值:
- 返回值通常存储在 EAX 寄存器中。
- 使用场景:
- 适合需要可变参数的函数,例如
printf
。
- 适合需要可变参数的函数,例如
示例
#include <stdio.h>void __cdecl my_function(int a, double b) {printf("a: %d, b: %f\n", a, b);
}int main() {my_function(10, 3.14);return 0;
}
2. __stdcall
调用约定
- 定义:
__stdcall
主要用于 Windows API,适合参数数量已知且固定的函数。 - 参数传递:
- 参数同样从右到左压入堆栈。
- 堆栈清理:
- 由被调用者负责清理堆栈,函数返回时会自动清理参数。
- 返回值:
- 返回值通常存储在 EAX 寄存器中。
- 使用场景:
- 主要用于 Windows API 和 DLL 函数。
示例
#include <windows.h>void __stdcall my_function(int a, double b) {// 进行一些操作
}int main() {my_function(10, 3.14);return 0;
}
3. __fastcall
调用约定
- 定义:
__fastcall
是一种较快的调用约定,使用寄存器传递前两个参数,可以减少堆栈操作。 - 参数传递:
- 前两个参数通过寄存器(通常是 ECX 和 EDX)传递,其余参数从右到左压入堆栈。
- 堆栈清理:
- 由调用者负责清理堆栈。
- 返回值:
- 返回值通常存储在 EAX 寄存器中。
- 使用场景:
- 适用于对性能有较高要求的场合,尤其是参数数量少且频繁调用的函数。
示例
void __fastcall my_function(int a, int b) {// 进行一些操作
}int main() {my_function(10, 20);return 0;
}
4. __thiscall
调用约定
- 定义:
__thiscall
是 C++ 中的默认调用约定,用于类的成员函数。 - 参数传递:
this
指针通过 ECX 寄存器传递,其余参数从右到左压入堆栈。
- 堆栈清理:
- 由调用者负责清理堆栈。
- 返回值:
- 返回值通常存储在 EAX 寄存器中。
- 使用场景:
- 主要用于 C++ 的成员函数,适合面向对象编程。
示例
class MyClass {
public:void __thiscall my_method(int a) {// 进行一些操作}
};int main() {MyClass obj;obj.my_method(10);return 0;
}
总结
调用约定 | 参数传递顺序 | 堆栈清理方式 | 适用场景 |
---|---|---|---|
__cdecl | 从右到左压入堆栈 | 调用者清理堆栈 | 可变参数函数 |
__stdcall | 从右到左压入堆栈 | 被调用者清理堆栈 | Windows API 和 DLL继续深入探讨各种调用约定,特别是 __cdecl 、__stdcall 、__fastcall 和 __thiscall 的具体特点、优缺点、以及在实际开发中的应用场景。 |
5. 各调用约定的优缺点
1. __cdecl
-
优点:
- 支持可变参数函数,可以处理像
printf
这样的函数。 - 由于调用者清理堆栈,提供了灵活性。
- 支持可变参数函数,可以处理像
-
缺点:
- 每次调用后,调用者都需要清理堆栈,相对来说效率较低。
- 不适用于需要固定参数数量的情况下,可能导致参数处理上的复杂性。
2. __stdcall
-
优点:
- 堆栈清理的责任在被调用者,简化了调用者的负担。
- 相较于
__cdecl
,在非可变参数函数中,堆栈的操作更加高效。
-
缺点:
- 不支持可变参数,不适合需要动态参数数量的函数。
- 在某些平台或编译器中可能不被广泛支持。
3. __fastcall
-
优点:
- 通过寄存器传递参数,减少了堆栈操作,提高了函数调用的效率。
- 特别适合频繁调用的函数,能显著提高性能。
-
缺点:
- 限制了能够通过寄存器传递的参数数量(通常只能前两个)。
- 代码的可移植性会受到影响,因为不同的平台对寄存器分配的处理可能不同。
4. __thiscall
-
优点:
- 适用于 C++ 的类成员函数,
this
指针的传递使得成员函数调用更加高效。 - 通过寄存器传递
this
指针,减少了堆栈的负担。
- 适用于 C++ 的类成员函数,
-
缺点:
- 仅适用于 C++,对于其他语言或非成员函数不适用。
- 不同编译器可能对其实现有所不同,可能导致兼容性问题。
6. 实际应用中的选择
在实际开发中,选择合适的调用约定非常重要,以下是一些选择调用约定时的考虑因素:
-
函数的参数数量和类型:
- 如果函数参数数量不固定,使用
__cdecl
。 - 如果参数数量固定且不多,使用
__stdcall
或__fastcall
。
- 如果函数参数数量不固定,使用
-
性能要求:
- 对于性能敏感的应用,
__fastcall
是更优的选择,因为它减少了堆栈操作。
- 对于性能敏感的应用,
-
平台和编译器支持:
- 确保所选调用约定在目标平台和编译器中被广泛支持,以避免兼容性问题。
-
代码可读性和维护性:
- 选择调用约定时要考虑团队的熟悉程度和代码的可维护性。
7. 其他常见调用约定
除了上述提到的调用约定,以下是一些其他常见的调用约定:
-
__vectorcall
:- 用于优化向量和浮点运算,参数通过寄存器传递,适合 SIMD 操作。
-
__regcall
:- 允许更灵活的寄存器使用,通常用于特定的性能优化场景。
-
__usercall
:- 允许用户自定义堆栈和寄存器的使用,不常用,主要用于高级优化。
8. 总结
调用约定在 C/C++ 编程中扮演着重要的角色,影响着程序的性能、可读性和兼容性。正确的调用约定选择能够有效提高程序的效率,减少错误和不必要的性能损失。开发者在编写代码时,应该根据具体的需求和上下文选择最合适的调用约定,以实现最佳的程序性能和可维护性。
相关文章:
c/c++ stdcall cdel fastcall等函数调用约定说明
调用约定(Calling Conventions)是编程中定义函数如何接收参数、返回值以及如何管理堆栈的协议。主要的调用约定包括 __cdecl、__stdcall、__fastcall 和 __thiscall 等。下面将详细介绍这些调用约定的特点及其适用场景。 1. __cdecl 调用约定 定义&…...

【ROS概述】概念及环境搭建
学习途径: 教程:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 课程视频:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 机器人体系 要完全实现一个机器人的系统研发,几乎是“全栈”开发,…...

MongoDB Shell 基本命令(三)生成学生脚本信息和简单查询
一、生成学生信息脚本 利用该脚本可以生成任意个学生信息,包括学号、姓名、班级、年级、专业、课程名称、课程成绩等信息,此处生成2万名学生,学生所有信息都是给定范围后随机生成。 生成学生信息后,再来对学生信息进行简单查询。…...

java核心技术点都有哪些
1. 面向对象编程(OOP) 核心概念:类、对象、继承、封装、多态。 比喻:面向对象编程就像是在搭建一个积木城堡。类(Class)是城堡的设计图纸,它定义了城堡的结构和功能;对象(…...
4404 - 提高:二分与三分:曲线(三分)
明明做作业的时候遇到了n个二次函数Si(x)=ax22+bx+c,他突发奇想设计了一个新的函数F(x)=max(Si(x)), i=1,2...n。 明明现在想求这个函数在[0,10000]的最小值,要求精确到小数点后四位四舍五入。 输入 输入包含T 组数据 (T<10) ,每组第一行一个整数 n(n≤10000) ,之后n行…...

软件工程--需求分析与用例模型
面向对象分析(ObjectOrientedAnalysis,简称OOA) 分析和理解问题域,找出描述问题域所需的类和对象,分析它们的内部构成和外部关系,建立独立于实现的OOA模型,暂时忽略与系统实现有关的问题。 主要使用UML中的以下几种图…...

预测房价学习
1. 实现函数来方便下载数据 import hashlib import os import tarfile import zipfile import requestsDATA_HUB dict() DATA_URL http://d2l-data.s3-accelerate.amazonaws.com/def download(name, cache_diros.path.join(.., data)):"""下载一个DATA_HUB中…...

电脑无法上网,但是微信、QQ可以正常使用
这种情况一般是由于DNS服务器配置错误,或者已有的DNS服务器无法正常解析地址造成的。 按下winR打开运行,输入ncpa.cpl,点击确定。 在打开的网络连接窗口中找到对应的网卡,双击打开。一般有线网是“以太网”,无线网&am…...

C++11新特性(列表初始化与右值引用折叠与完美转发)
c11 列表初始化c98的{}c11的{}std::initializer_list 右值引用和移动语义左值和右值的概念左值引用和右值引用引用延长临时对象生命周期左值和右值的参数匹配左值引用的主要使用场景移动构造和移动赋值引用折叠完美转发 列表初始化 c98的{} 在C98中,大括号 {} 的使…...

基于SSH的物流运输货运车辆管理系统源码
基于经典的ssh(Spring Spring MVC Hibernate)框架与SaaS(软件即服务)模式,我们为运输企业与物流公司打造了一款开源且易用的车辆管理系统。 该系统主要包含以下核心模块: 档案管理 财务管理 借款管理 保…...

基于RabbitMQ,Redis,Redisson,RocketMQ四种技术实现订单延时关闭功能及其相关优缺点介绍(以12306为主题)
目录 1. 延迟关闭订单 1.1 订单延时关闭功能技术选型 1.1.1 定时任务 1.1.2 RabbitMQ 1.1.3 Redis 过期监听 1.1.4 Redisson 1.1.5 RocketMQ 1.2 RocketMQ订单延时关闭发送方实现 1.3 RocketMQ订单延时关闭的消费方实现 1. 延迟关闭订单 用户发起订单后,如…...

HarmonyOS ArkTS与C++数据类型转换
1. HarmonyOS ArkTS与C数据类型转换 本文介绍了C与TS各自数据类型与互相之间的数据类型转换,在需要使用C模块时可以快速上手对各种数据类型进行转换。 1.1. 概述 HarmonyOS的主力开发语言是ArkTS,也提供了C语言的支持,对于一些能力ÿ…...

腾讯云或阿里云centos7安装Redis,并解决端口无法访问的问题
问题背景 最近自建的网站JeecgFlow在云环境安装redis时候,出现端口无法远程进行访问。 浪费好了好久时间进行排查, 记录一下Redis在云环境centos7环境下如何安装,并且远程访问。 Redis安装 //安装c 用于编译redis yum install gcc-c//在/u…...
【小问题】距离估计和频率估计的方差下界推导出距离估计的方差下界
【1】OFDM Radar Algorithms in Mobile Communication Networks pp34 文章目录 1. 频率和距离之间的关系2. 计算 d ^ \hat{d} d^ 对 n ^ \hat{n} n^ 的导数3. 将频率的方差转化为距离的方差4. 从频率的 CRB 获得 var [ n ^ ] \operatorname{var}[\hat{n}] var[n^]5. 将 …...

Selenium爬虫技术:如何模拟鼠标悬停抓取动态内容
介绍 在当今数据驱动的世界中,抓取动态网页内容变得越来越重要,尤其是像抖音这样的社交平台,动态加载的评论等内容需要通过特定的方式来获取。传统的静态爬虫方法难以处理这些由JavaScript生成的动态内容,Selenium爬虫技术则是一…...

Z-BlogPHP显示错误Undefined array key 0 (set_error_handler)的解决办法
今天打开博客的时候,意外发现页面,打开均显示错误:Undefined array key 0 (set_error_handler)。 博客程序采用的是Z-BlogPHP。百度了一圈没有找到解决办法,在官方论坛里也没找到解决办法。 于是开始自己排查原因。我服务器采用…...
java-实例化一个List,然后添加数据的方法详解
在Java中,实例化一个 List 并向其中添加数据非常简单。List 是一个接口,因此我们通常使用它的常见实现类 ArrayList 或 LinkedList。以下是一些常见的操作方法: ### 1. 使用 ArrayList 实例化并添加数据 java import java.util.ArrayList; …...

【Linux系统】Ubuntu的简单操作
什么是 Ubuntu? Ubuntu(乌帮图)是一个非洲词汇,它的意思是“人性对待他人”或“群在故我在”。Ubuntu发行版将Ubuntu精神带到软件世界之中。 目前已有大量各种各样基于GNU/Linux的操作系统,例如:Debian,SuSE,Gentoo,R…...

标准日志插件项目【C/C++】
博客主页:花果山~程序猿-CSDN博客 文章分栏:项目日记_花果山~程序猿的博客-CSDN博客 关注我一起学习,一起进步,一起探索编程的无限可能吧!让我们一起努力,一起成长! 目录 一,项目介…...

SpingBoot原理
SpingBoot原理 在前面十多天的课程当中,我们学习的都是web开发的技术使用,都是面向应用层面的,我们学会了怎 么样去用。而我们今天所要学习的是web后端开发的最后一个篇章springboot原理篇,主要偏向于底 层原理。 我们今天的课程…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...