当前位置: 首页 > news >正文

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++,对于其他语言或非成员函数不适用。
    • 不同编译器可能对其实现有所不同,可能导致兼容性问题。

6. 实际应用中的选择

在实际开发中,选择合适的调用约定非常重要,以下是一些选择调用约定时的考虑因素:

  • 函数的参数数量和类型

    • 如果函数参数数量不固定,使用 __cdecl
    • 如果参数数量固定且不多,使用 __stdcall__fastcall
  • 性能要求

    • 对于性能敏感的应用,__fastcall 是更优的选择,因为它减少了堆栈操作。
  • 平台和编译器支持

    • 确保所选调用约定在目标平台和编译器中被广泛支持,以避免兼容性问题。
  • 代码可读性和维护性

    • 选择调用约定时要考虑团队的熟悉程度和代码的可维护性。

7. 其他常见调用约定

除了上述提到的调用约定,以下是一些其他常见的调用约定:

  • __vectorcall

    • 用于优化向量和浮点运算,参数通过寄存器传递,适合 SIMD 操作。
  • __regcall

    • 允许更灵活的寄存器使用,通常用于特定的性能优化场景。
  • __usercall

    • 允许用户自定义堆栈和寄存器的使用,不常用,主要用于高级优化。

8. 总结

调用约定在 C/C++ 编程中扮演着重要的角色,影响着程序的性能、可读性和兼容性。正确的调用约定选择能够有效提高程序的效率,减少错误和不必要的性能损失。开发者在编写代码时,应该根据具体的需求和上下文选择最合适的调用约定,以实现最佳的程序性能和可维护性。

相关文章:

c/c++ stdcall cdel fastcall等函数调用约定说明

调用约定&#xff08;Calling Conventions&#xff09;是编程中定义函数如何接收参数、返回值以及如何管理堆栈的协议。主要的调用约定包括 __cdecl、__stdcall、__fastcall 和 __thiscall 等。下面将详细介绍这些调用约定的特点及其适用场景。 1. __cdecl 调用约定 定义&…...

【ROS概述】概念及环境搭建

学习途径&#xff1a; 教程&#xff1a;Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 课程视频&#xff1a;https://www.bilibili.com/video/BV1Ci4y1L7ZZ 机器人体系 要完全实现一个机器人的系统研发&#xff0c;几乎是“全栈”开发&#xff0c;…...

MongoDB Shell 基本命令(三)生成学生脚本信息和简单查询

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

java核心技术点都有哪些

1. 面向对象编程&#xff08;OOP&#xff09; 核心概念&#xff1a;类、对象、继承、封装、多态。 比喻&#xff1a;面向对象编程就像是在搭建一个积木城堡。类&#xff08;Class&#xff09;是城堡的设计图纸&#xff0c;它定义了城堡的结构和功能&#xff1b;对象&#xff08…...

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&#xff0c;简称OOA) 分析和理解问题域&#xff0c;找出描述问题域所需的类和对象&#xff0c;分析它们的内部构成和外部关系&#xff0c;建立独立于实现的OOA模型&#xff0c;暂时忽略与系统实现有关的问题。 主要使用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服务器配置错误&#xff0c;或者已有的DNS服务器无法正常解析地址造成的。 按下winR打开运行&#xff0c;输入ncpa.cpl&#xff0c;点击确定。 在打开的网络连接窗口中找到对应的网卡&#xff0c;双击打开。一般有线网是“以太网”&#xff0c;无线网&am…...

C++11新特性(列表初始化与右值引用折叠与完美转发)

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

基于SSH的物流运输货运车辆管理系统源码

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

基于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. 延迟关闭订单 用户发起订单后&#xff0c;如…...

HarmonyOS ArkTS与C++数据类型转换

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

腾讯云或阿里云centos7安装Redis,并解决端口无法访问的问题

问题背景 最近自建的网站JeecgFlow在云环境安装redis时候&#xff0c;出现端口无法远程进行访问。 浪费好了好久时间进行排查&#xff0c; 记录一下Redis在云环境centos7环境下如何安装&#xff0c;并且远程访问。 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爬虫技术:如何模拟鼠标悬停抓取动态内容

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

Z-BlogPHP显示错误Undefined array key 0 (set_error_handler)的解决办法

今天打开博客的时候&#xff0c;意外发现页面&#xff0c;打开均显示错误&#xff1a;Undefined array key 0 (set_error_handler)。 博客程序采用的是Z-BlogPHP。百度了一圈没有找到解决办法&#xff0c;在官方论坛里也没找到解决办法。 于是开始自己排查原因。我服务器采用…...

java-实例化一个List,然后添加数据的方法详解

在Java中&#xff0c;实例化一个 List 并向其中添加数据非常简单。List 是一个接口&#xff0c;因此我们通常使用它的常见实现类 ArrayList 或 LinkedList。以下是一些常见的操作方法&#xff1a; ### 1. 使用 ArrayList 实例化并添加数据 java import java.util.ArrayList; …...

【Linux系统】Ubuntu的简单操作

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

标准日志插件项目【C/C++】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;项目日记_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;项目介…...

SpingBoot原理

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

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...