当前位置: 首页 > 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;主要偏向于底 层原理。 我们今天的课程…...

Cout输出应用举例

Cout输出应用 在main.cpp里输入程序如下&#xff1a; #include <iostream> //使能cin(),cout(); #include <stdlib.h> //使能exit(); #include <sstream> #include <iomanip> //使能setbase(),setfill(),setw(),setprecision(),setiosflags()和res…...

java的无锁编程和锁机制

Java 的并发编程中&#xff0c;为了保证线程安全和高性能&#xff0c;采用了两种主要的同步手段&#xff1a;锁机制和无锁编程。以下是对锁机制、无锁编程、死锁及其避免的详细讲解。 一、无锁编程 无锁编程通过原子操作来避免传统锁&#xff0c;从而减少线程的上下文切换&am…...

vue实现富文本编辑器上传(粘贴)图片 + 文字

vue实现富文本编辑器上传&#xff08;粘贴&#xff09;图片 文字 1.安装插件 npm install vue-quill-editor -s2.在使用vue-quill-editor富文本的时候&#xff0c;对于图片的处理经常是将图片转换成base64&#xff0c;再上传数据库&#xff0c;但是base64不好存储。 原理&a…...

子集和全排列(深度优先遍历)问题

欢迎访问杀马特主页&#xff1a;小小杀马特主页呀&#xff01; 目录 前言&#xff1a; 例题一全排列&#xff1a; 1.题目介绍&#xff1a; 2.思路汇总&#xff1a; 3.代码解答&#xff1a; 例题二子集&#xff1a; 题目叙述&#xff1a; 解法一&#xff1a; 1.思路汇总…...

判断检测框是否在感兴趣区域(ROI)内

判断检测框是否在感兴趣区域&#xff08;ROI&#xff09;内 在计算机视觉和图像处理中&#xff0c;我们经常需要确定一个矩形检测框是否位于一个特定的感兴趣区域&#xff08;Region of Interest, ROI&#xff09;内。这个ROI可以是一个多边形&#xff0c;而检测框则是一个矩形…...

正点原子阿尔法ARM开发板-IMX6ULL(九)——关于SecureCRT连接板子上的ubuntu

文章目录 一、拨码器二、SecureCRT 一、拨码器 emmm,也是好久没学IMX6ULL了&#xff0c;也是忘了拨码器决定了主板的启动方式 一种是直接从TF卡中读取文件&#xff08;注意这里是通过imdownload软件编译好了之后&#xff0c;通过指令放入TF卡&#xff09; 一种是现在这种用串口…...

微信支付Java+uniapp微信小程序

JS&#xff1a; request.post(/vip/pay, {//这是自己写的java支付接口id: this.vipInfo.id,payWay: wechat-mini}).then((res) > {let success (res2) > {//前端的支付成功回调函数this.$refs.popup.close();// 支付成功刷新当前页面setTimeout(() > {this.doGetVipI…...

【NOIP提高组】加分二叉树

【NOIP提高组】加分二叉树 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 设一个n个节点的二叉树tree的中序遍历为&#xff08;l,2,3,…,n&#xff09;&#xff0c;其中数字1,2,3,…,n为节点编号。每个节点都有一个分数&#xff08;均为正整…...

HarmonyOS 相对布局(RelativeContainer)

1. HarmonyOS 相对布局&#xff08;RelativeContainer&#xff09; 文档中心:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-layout-development-relative-layout-V5   RelativeContainer为采用相对布局的容器&#xff0c;支持容器内部的子元素设…...

webpack5搭建react脚手架详细步骤

1. 初始化项目 首先&#xff0c;创建一个新目录并初始化项目&#xff1a; bash mkdir create-react cd create-react pnpm init --y git init 这里使用pnpm作为包管理工具&#xff0c;因为它在处理依赖和速度上表现更好。 2. 安装React和TypeScript 安装React和React-DOM…...

网站建设的流程图示/淘宝站外引流推广方法

重构学习笔记1. 封装集合                                                    概念&#xff1a;本文所讲的封装集合就是把集合进行封装&#xff0c;只提供调用端需要的接口。 正文&#xff1a;在很多时候&#xff0c;我们…...

大连网站设计收费标准/少儿培训

相信大家应该都知道&#xff0c;最近这段时间在网上以及B站上面有一些非常有意思的弹幕&#xff0c;而且看这些弹幕和评论真的是感觉非常的深奥&#xff0c;意思非常的有深意&#xff0c;比如说“人类的悲欢并不相通”&#xff0c;这句话是什么意思呢&#xff1f;下面就和小编一…...

b2c网站的认识/哪里可以代写软文

对于大部分IT人士来说&#xff0c;给电脑重装系统、迁移操作系统、给硬盘分区、磁盘分区克隆等都是经常要做且不得不做的事情&#xff0c;那么使用哪款软件来管理磁盘分区&#xff0c;就成了大多数人比较纠结的问题。究竟有没有什么分区管理软件是比较靠谱又安全的呢&#xff1…...

济南做网站哪好/郑州网络推广方案

CPU&#xff08;Central Processing Unit&#xff0c;中央处理器&#xff09;发展出来三个分枝&#xff0c;一个是DSP&#xff08;Digital Signal Processing/Processor&#xff0c;数字信号处理&#xff09;&#xff0c;另外两个是MCU&#xff08;Micro Control Unit&#xff…...

深圳网站建设工作室/周口网站seo

做 Java 开发的你&#xff0c;一天是不是这样度过的&#xff1f;8:00--9:30 闹铃响了N遍后&#xff0c;匆忙起床洗漱&#xff0c;在拥挤的地铁上刷朋友圈、公众号和技术论坛9:30--10:00 到公司&#xff0c;吃早点&#xff0c;打开电脑收邮件&#xff0c;终终终于准备好状态开始…...

wordpress部署https/廊坊首页霸屏优化

集群配置&#xff1a;1个nsqlookupd, 1个nsqadmin&#xff0c;3个nsqd 分区&#xff1a;1个order-topic&#xff0c;分区数为100&#xff0c;副本数为3 扩容时&#xff0c;新增一个nsqd-4。刚开始&#xff0c;nsqd-4没有任何分区副本。 接下来通过nsqadmin页面发现&#xff…...