什么是函数调用约定?

目录

前言

一、函数调用约定的主要内容

二、常见的函数调用约定

1. __cdecl(C Declaration)

2. __stdcall(Standard Call)

3. __fastcall(Fast Call)

4. __thiscall(This Call)

5. __pascal

三、选择合适的调用约定

四、注意事项


前言

函数调用约定(Calling Convention)是在程序设计中定义函数如何调用和返回的一套规则。它规定了函数参数的传递方式、返回值的处理、堆栈的管理以及函数名的修饰方式等。不同的调用约定可能会影响程序的性能和可移植性,因此理解它们对于高效编程和调试非常重要。

一、函数调用约定的主要内容

  1. 参数传递方式

    • 传递顺序:参数是从左到右还是从右到左依次压入堆栈。
    • 传递方式:参数是通过寄存器传递还是通过堆栈传递。
  2. 堆栈管理

    堆栈清理者:调用者(caller)还是被调用者(callee)负责在函数调用结束后清理堆栈上的参数。
  3. 返回值处理

    返回值通常通过寄存器(如 EAX)传递。
  4. 函数名修饰

    编译器如何处理函数名,以支持函数重载和避免命名冲突。

二、常见的函数调用约定

1. __cdecl(C Declaration)

  • 参数传递

    • 顺序:从右到左依次压入堆栈。
    • 方式:通过堆栈传递。
  • 堆栈管理

    • 由调用者清理堆栈。这意味着调用者在函数调用后需要负责移除参数。
  • 返回值

    • 通常通过 EAX 寄存器返回。
  • 函数名修饰

    • 在函数名前加上下划线(如 _FunctionName)。
    • 适用于可变参数函数(如 printf),因为调用者负责堆栈清理,函数本身不需要知道参数的个数。
  • 特点

    • 是 C 语言的默认调用约定。
    • 支持函数重载。
  • 示例

// 声明
int __cdecl add(int a, int b);// 定义
int __cdecl add(int a, int b) {return a + b;
}

2. __stdcall(Standard Call)

  • 参数传递

    • 顺序:从右到左依次压入堆栈。
    • 方式:通过堆栈传递。
  • 堆栈管理

    • 由被调用者清理堆栈。这意味着被调用的函数在返回前负责移除参数。
  • 返回值

    • 通常通过 EAX 寄存器返回。
  • 函数名修饰

    • 在函数名后加上 @ 和参数的字节数(如 FunctionName@8)。
    • 在函数名前加上下划线(如 _FunctionName@8)。
  • 特点

    • 常用于 Windows API 函数。
    • 不支持可变参数函数。
  • 示例

// 声明
int __stdcall add(int a, int b);// 定义
int __stdcall add(int a, int b) {return a + b;
}

3. __fastcall(Fast Call)

  • 参数传递

    • 顺序:前两个双字(DWORD)或更小的参数通过寄存器传递(通常是 ECXEDX),剩余参数从右到左压入堆栈。
  • 堆栈管理

    • 由被调用者清理堆栈。
  • 返回值

    • 通常通过 EAX 寄存器返回。
  • 函数名修饰

    • 在函数名前加上 @,并在函数名后加上 @ 和参数的字节数(如 @FunctionName@8)。
  • 特点

    • 通过使用寄存器传递部分参数,提高调用效率。
    • 适用于参数较少且频繁调用的函数。
  • 示例

// 声明
int __fastcall add(int a, int b);// 定义
int __fastcall add(int a, int b) {return a + b;
}

4. __thiscall(This Call)

  • 适用范围

    • 专用于 C++ 类的成员函数调用。
  • 参数传递

    • 顺序:从右到左依次压入堆栈。
    • 方式:通过堆栈传递参数,this 指针通过寄存器(通常是 ECX)传递
  • 堆栈管理

    • 由被调用者清理堆栈。
  • 返回值

    • 通常通过 EAX 寄存器返回。
  • 函数名修饰

    • 编译器根据具体实现进行修饰,通常与其他调用约定不同。
  • 特点

    • 不能显式指定为函数调用约定,编译器会自动处理。
    • 仅适用于成员函数,不适用于普通函数。
  • 示例

class MyClass {
public:void memberFunction(int a, int b);
};// 编译器会自动使用 __thiscall 调用约定
void MyClass::memberFunction(int a, int b) {// 实现
}

5. __pascal

  • 状态

    • 已被废弃:在现代 Visual C++ 中,__pascal 已经被废弃,不再推荐使用。
  • 特点

    • 参数传递顺序与 __stdcall 类似,但从左到右压入堆栈。
    • 被早期的 Pascal 语言调用约定所采用。
  • 示例

// 已废弃,不推荐使用
int __pascal add(int a, int b);

三、选择合适的调用约定

  1. 默认选择:对于普通的 C/C++ 函数,通常使用 __cdecl,因为它支持可变参数函数(如 printf)。
  2. 性能优化:对于频繁调用且参数较少的函数,可以考虑使用 __fastcall,通过寄存器传递部分参数,提高调用效率。
  3. 与外部库兼容:当调用 Windows API 函数或其他采用特定调用约定的外部库函数时,需使用对应的调用约定(如 __stdcall)。
  4. 类成员函数:不需要手动指定,编译器会自动使用 __thiscall 调用约定。

四、注意事项

  • 一致性:在同一个项目中,确保函数调用约定的一致性,避免因调用约定不匹配导致的程序错误或崩溃。

  • 跨语言调用:当在不同编程语言之间调用函数时,需确保双方使用相同的调用约定,以保证参数传递和堆栈管理的正确性。

  • 编译器支持: 不同的编译器可能对调用约定的支持有所不同,使用前应查阅相应编译器的文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/52059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring Boot 3】【Web】国际化

【Spring Boot 3】【Web】国际化 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或…

[数据集][目标检测]轮胎检测数据集VOC+YOLO格式4629张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):4629 标注数量(xml文件个数):4629 标注数量(txt文件个数):4629 标注…

【SQL】删除表中重复数据的方法

很久之前我写入一张sql的数据表,它里面有很多重复的内容。然后我想只保留一条原始数据: 例如上面的时间,出现了很多重复值。 我最初用的是这种方法: SELECT * FROM table_name WHERE primary_key IN (SELECT max(primary_key)F…

ubuntu20.04 colmap安装

apt-get update apt-get install colmap 官方包网址: colmap_3.6really3.6-1_amd64.deb Debian 11 Download (pkgs.org) 官方安装非常简单,但是看网上都是手动安装教程,都麻烦的要命!我也踩了两天雷,还是看github上…

仕考网:公务员笔试和面试哪个难?

公务员笔试和面试哪个难?二者之间考察的方向不同,难度也是不同的。 笔试部分因其广泛的知识点和有限的考试时间显得难度更高一些,在笔试环节中,考生需在有限的时间内应对各种问题,而且同时还要面对激烈的竞争,在众多…

Java的内存泄漏和性能瓶颈

内存泄漏 ‌内存泄漏‌指的是程序中已分配的内存由于某种原因无法被释放或回收,导致内存的浪费和潜在的程序崩溃。在Java中,由于有垃圾回收机制(GC),直接的内存泄漏相对较少,但间接的内存泄漏仍然可能发生…

栈栈栈专题

一、基础 Leetcode 3174. 清除数字 class Solution { public:string clearDigits(string s) {string st; // 用string模拟栈的行为for(auto& v: s){if(isdigit(v)) st.pop_back();else st v;}return st;} }; 二、进阶 三、邻项消除 四、合法括号字符串 五、…

每日一题——第八十题

题目&#xff1a;输入十个整数&#xff0c;将其中最小的数与第一个数交换&#xff0c;将最大的数与最后一个数对调 #include <stdio.h> void swap(int *a, int *b) { int temp *a; *a *b; *b temp; } int main() { int numbers[10]; int i; int minIndex …

50Kg大载重长航时油电混动多旋翼无人机技术详解

50Kg大载重长航时油电混动多旋翼无人机技术是一项高度复杂且前沿的研究领域&#xff0c;它结合了燃油发动机的高能量密度和电动机的高效性&#xff0c;旨在提高无人机的续航能力和载重能力。以下是对该技术的详细解析&#xff1a; 产品轴距&#xff1a;2320mm 产品尺寸&#x…

数仓建模—维度建模之维度表

数仓建模—维度建模之维度表 维度表(Dimension Table)是数据仓库中描述业务过程中各种维度信息的表,用于提供上下文和描述性信息,以丰富事实数据的分析 维度表是维度建模的灵魂所在,在维度表设计中碰到的问题(比如维度变化、维度层次、维度一致性、维度整合和拆分等)都…

Django+Vue家居全屋定制系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作者&…

今年读过最绝的大模型神书死磕这本大模型神书!看完直接脱胎换骨!!

书名&#x1f4d6;&#xff1a;《大语言模型&#xff1a;基础与前沿》 该书深入阐述了大语言模型&#xff08;Large Language Model, LLM&#xff09;的基本概念和算法、研究前沿以及应用&#xff0c;内容全面且系统性强&#xff0c;适合&#x1f468;&#x1f3fb;‍&#x1…

踩坑记录-20240904--qt

1&#xff1a;请求接口没有数据 &#xff0c;请把本地的接口缓存清空&#xff0c;确保接口是从网络中拿数据 拿不到数据的情况下 接口判断是否从缓存中拿去数据也是false的情况 2&#xff1a;异步请求嵌套异步请求 要注意延时性的问题 因为第二个异步请求结束的时候 前面异步…

Oracle WITH简单例子

假设有一个名为 students 的表&#xff0c;包含字段 student_id、student_name、score 现在要查询成绩大于等于 80 分的学生信息以及所有学生的平均成绩。 WITH high_score_students AS (SELECT student_id, student_name, scoreFROM studentsWHERE score > 80 ) SELECT h…

【Python系列】FastApi发送Post请求

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

安装 Let‘s Encrypt certbot 生成多个域名免费 https 证书实录(linux pip 方式)

本文记录了我在华为云 EulerOS linux 云主机使用 python pip 方式安装配置 Let’s Encrypt certbot, 并为我的网站的多个域名生成免费 https 证书的整个过程, 包括 python 环境配置, 下载 certbot 及 certbot-nginx, 一次性生成多个域名的证书及注意事项, 以及最后配置 certbot…

Arduino IDE

Arduino IDE&#xff08;集成开发环境&#xff09;的安装过程是一个相对直观且易于操作的流程&#xff0c;主要步骤包括下载、安装和配置。以下将详细阐述Arduino IDE的安装过程&#xff0c;同时提供一些背景信息和注意事项&#xff0c;确保安装过程顺利进行。 一、Arduino ID…

k8s配置

一、前期准备 1、修改主机的/etc/hosts文件挟持域名 [rootk8s-master ~]# vim /etc/hosts 192.168.8.199 k8s-master 192.168.8.200 k8s-node1 192.168.8.201 k8s-node2 2、配置yum源 [rootk8s-master ~]# cd /etc/yum.repos.d/ [rootk8s-master yum.repos.d]# vim kubernetes…

MVVM 设计模式:构建高效且可维护的前端应用

在现代前端开发中&#xff0c;随着应用规模的不断扩大和复杂性的增加&#xff0c;采用合适的设计模式变得尤为重要。MVVM&#xff08;Model-View-ViewModel&#xff09;作为一种流行的设计模式&#xff0c;它通过分离业务逻辑和用户界面&#xff0c;提高了代码的可维护性和可测…

【代码随想录|图论part03之后】

代码随想录|数组 704. 二分查找,27. 移除元素 一、part031、101. 孤岛的总面积1.1 dfs版本1.2 BFS版本2.102. 沉没孤岛3、103. 水流问题4、104.建造最大岛屿二、part041、110. 字符串接龙2、105.有向图的完全可达性3、106. 岛屿的周长三、part05-06 并查集理论1、107. 寻找存在…