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原理篇,主要偏向于底 层原理。 我们今天的课程…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
