C/C++中的调用约定
在C/C++编程中,调用约定(calling conventions)是一组指定如何调用函数的规则。主要在你调用代码之外的函数(例如OS API,操作系统应用程序接口)或OS调用你(如WinMain的情况)时起作用。如果编译器不知道正确的调用约定,那么你很可能会遇到非常奇怪的崩溃,因为堆栈将无法正确管理。调用约定用于确保函数在不同平台和编译器之间正确且一致地调用。调用约定有助于标准化编译器的函数调用和参数传递方式,标准化可实现编程语言之间的互操作性。
并非所有约定都在所有支持的平台上可用,某些约定使用平台特定的实现。在大多数情况下,将忽略在特定平台上指定不支持的约定的关键字或编译器开关,并将使用平台默认约定。
调用约定通常在函数声明或定义时通过特定的关键字或属性指定。例如,在MSVC中,可以使用__cdecl、__stdcall、__fastcall等关键字来指定调用约定。在GCC中,可以使用__attribute__((cdecl))、__attribute__((stdcall))等属性来指定调用约定。在跨平台开发或调用第三方库时,需要特别注意调用约定的匹配。
C/C++中的调用约定是确定以下准则:
(1).如何将参数传递到堆栈。
(2).谁将清除堆栈,调用者还是被调用者?
(3).将使用哪些寄存器以及如何使用。
C++代码在编译阶段结束时转换为目标代码(object code)。然后我们得到目标文件(object file)。目标文件链接在一起以创建二进制文件(如exe、lib、dll)。在创建目标文件之前,我们可以告诉编译器停止并给我们.asm文件。这是将转换为目标文件的汇编文件。不同的调用约定会产生不同的汇编代码(Different calling conventions produce different assembly codes)。
MSVC支持几种函数的调用约定:"__cdecl"、"__stdcall"、"__fastcall"等,默认情况下MSVC把C语言的函数当作"__cdecl"类型,这种情况下它对该函数不进行任何符号修饰。但是一旦我们使用其它的函数调用约定时,MSVC编译器就会对符号名进行修饰,比如使用"__stdcall"调用约定的函数Add就会被修饰成"_Add@16",前面以"_"开头,后面以"@n"结尾,n表示函数调用时参数所占堆栈空间的大小。使用.def文件可以将导出函数重新命名。当一个DLL被多个语言编写的模块使用时,采用这种方法导出一个函数往往会很有用。我们经常看到Windows的API都采用"WINAPI"这种方式声明,而"WINAPI"实际上是一个被定义为"__stdcall"的宏。微软以DLL的形式提供Windows的API,而每个DLL中的导出函数又以这种"__stdcall"的方式被声明。
MSVC下不同的调用约定:使用时将以下修饰符放置在变量或者函数名称的前面,告诉编译器设置堆栈、推送参数和获取返回值的规则
1.__cdecl:C declaration,C/C++程序的默认调用约定。是一种"干净"的调用约定,不使用任何特殊指令或寄存器来传递函数参数或返回值。
(1).参数从右向左依次入栈(因此第一个参数最接近堆栈顶部)。
(2).调用者负责清理堆栈,即调用者会在返回后弹出所有参数。
(3).创建比__stdcall更大的可执行文件,因为它要求每个函数调用都包含堆栈清理代码。
(4).当调用者按照此约定清理堆栈时,我们可以为使用__cdecl调用约定的函数提供可变参数。
2.__stdcall:Standard Call,Win32 API函数使用的特定于Microsoft的调用约定。
(1).参数从右向左依次入栈(因此第一个参数最接近堆栈顶部)。
(2).被调用者(自身)负责清理堆栈,即被调用者在返回前会弹出所有参数。
3.__fastcall:在__fastcall调用约定中,如果可能的话,参数会被传递给寄存器。
(1).前两个参数(从左到右的顺序)通过寄存器ECX和EDX传递。其余参数从右向左依次入栈。
(2).被调用者负责清理堆栈。
4.__thiscall:仅适用于C++,类内方法使用的默认调用约定。
(1).参数从右向左依次入栈。
(2).this指针通过寄存器ECX传递,而不是在堆栈上传递。
(3).不能对非成员函数使用此调用约定。
(4).被调用者负责清理堆栈。
(5).__thiscall只能出现在非静态成员函数上。
在C/C++中使用调用约定的优点:
1.兼容性:不同的平台和编译器对函数参数的传递方式和返回值的返回方式可能有不同的要求。通过使用特定的调用约定,你可以确保你的代码与不同的平台和编译器兼容。
2.一致性:使用一致的调用约定有助于确保你的代码易于阅读和理解。
3.优化:某些调用约定旨在比其他调用约定更高效。例如,__fastcall调用约定可以比__cdecl或__stdcall更快,因为它使用寄存器传递函数参数。这对于经常调用的函数尤其有用。
4.安全性:使用一致的调用约定有助于防止出现诸如堆栈损坏或返回值不正确等错误。
在C/C++中使用调用约定的缺点:
1.复杂性:使用不同的调用约定会增加代码的复杂性,尤其是在处理具有许多不同功能的大型项目时。这会使代码更难理解和维护。
2.兼容性问题:如果你使用的调用约定不受特定平台或编译器支持,则可能必须修改代码或使用不同的调用约定。这可能很耗时,并且可能需要进行额外的测试以确保代码仍然正确。
3.性能开销:某些调用约定可能会带来少量性能开销,尤其是在它们需要额外的指令或寄存器使用时。这对于大多数应用程序来说可能并不重要,但对于高性能代码来说,这可能是一个考虑因素。
4.可移植性:如果你使用的调用约定特定于特定平台或编译器,则你的代码可能无法移植到其他平台或编译器。如果你想在不同平台上重用代码,或者你正在使用混合环境,这可能会成为一个问题。
注:以上整理的内容主要来自:
1. https://www.geeksforgeeks.org
2. https://www.javatpoint.com
以下为测试代码:
#include "calling_convention.hpp"
#include <iostream>namespace {#ifdef _MSC_VER
#define CDECL __cdecl
#define STDCALL __stdcall
#define FASTCALL __fastcall
#define THISCALL __thiscall
#else
#define CDECL __attribute__((cdecl))
#define STDCALL __attribute__((stdcall))
#define FASTCALL __attribute__((fastcall))
#define THISCALL __attribute__((thiscall))
#endifint CDECL add_cdecl(int a, int b) { return (a + b); }
int STDCALL add_stdcall(int a, int b) { return (a + b); }
int FASTCALL add_fastcall(int a, int b) { return (a + b); }
class Tmp {
public:int THISCALL add_thiscall(int a, int b) { return (a + b); }
};} // namespaceint test_calling_convention()
{auto ret1 = add_cdecl(1, 2);auto ret2 = add_stdcall(1, 2);auto ret3 = add_fastcall(1, 2);Tmp tmp;auto ret4 = tmp.add_thiscall(1, 2);std::cout << "results: " << ret1 << "," << ret2 << "," << ret3 << "," << ret4 << std::endl;return 0;
}
GitHub:https://github.com/fengbingchun/Messy_Test
相关文章:
C/C++中的调用约定
在C/C编程中,调用约定(calling conventions)是一组指定如何调用函数的规则。主要在你调用代码之外的函数(例如OS API,操作系统应用程序接口)或OS调用你(如WinMain的情况)时起作用。如果编译器不知道正确的调用约定,那么你很可能会遇到非常奇怪…...
微信创建小程序码 - 数量不受限制
获取小程序码:小程序码为圆图,且不受数量限制。 目录 文档 接口地址 请求方式 功能描述 注意事项 获取 scene 值 请求参数 返回参数 对接 请求方法 获取小程序码 调用获取小程序码 总结 文档 接口地址 https://api.weixin.qq.com/wxa/get…...
springboot/ssm美食分享系统Java代码web项目美食烹饪笔记分享交流
springboot/ssm美食分享系统ava美食烹饪笔记分享交流系统web美食源码 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&#…...
【Redis篇】 List 列表
在 Redis 中,List 是一种非常常见的数据类型,用于表示一个有序的字符串集合。与传统的链表结构类似,Redis 的 List 支持在两端进行高效的插入和删除操作,因此非常适合实现队列(Queue)和栈(Stack…...
多级IIR滤波效果(BIQUAD),system verilog验证
MATLAB生成IIR系数 采用率1k,截止频率30hz,Matlab生成6阶对应的biquad3级系数 Verilog测试代码 // fs1khz,fc30hz initial beginreal Sig_Orig, Noise_white, Mix_sig;real fs 1000;Int T 1; //周期int N T*fs; //1s的采样点数// 数组声明…...
【WPF中ControlTemplate 与 DataTemplate之间的区别?】
前言 WPF中ControlTemplate 与 DataTemplate之间的区别? 1. 定义: ControlTemplate 是用于定义 WPF 控件的外观和结构的模板。它允许您重新定义控件的视觉表现,而不改变控件的行为。 DataTemplate 是用于定义如何呈现数据对象的模板。它通…...
Keil5配色方案修改为类似VSCode配色
1. 为什么修改Keil5配色方案 视觉习惯:如果你已经习惯了VSCode的配色方案,尤其是在使用ESP-IDF开发ESP32时,Keil5的默认配色可能会让你感到不习惯。减少视觉疲劳:Keil5的默认背景可能过于明亮,长时间使用可能会导致视…...
ndp协议简介
在IPv6中,ARP(地址解析协议)被替代为邻居发现协议(Neighbor Discovery Protocol,NDP)。NDP是IPv6网络中用于发现邻居节点(相邻设备)的协议,类似于IPv4中的ARP。但与ARP不…...
stable diffusion实践操作-大模型介绍:SD的发展历史,SD1.5和SDXL之间的差别
大家有没有这样的困惑:在找模型时,老是会出现一些奇怪的标签,像 sd1.5、sdxl 之类的模型后缀,真让人摸不着头脑,一会儿 1.0,一会儿 1.5,一会儿 XL,完全搞不清楚状况。今天就来给大家…...
系统无法运行提示:sqlsut.dll初始化错误怎么解决?多种解决方法汇总一览
遇到 sqlsut.dll 初始化错误,这通常意味着 SQL Server 的某些组件未能正确加载或初始化。以下是一些可能的解决方法汇总,旨在帮助您排查和解决问题: 解决方法 1. 检查SQL Server服务状态•确认所有相关的SQL Server服务(如SQL Se…...
通过waitress启动flask应用
假设你有一个名为 app.py 的文件,app 是指你的 Flask 应用实例。并且在这个文件中创建了一个 Flask 应用实例,那么你可以这样导入和使用它。 示例结构 假设你的项目结构如下: my_flask_app/ │ ├── app.py ├── waitress_server.py └─…...
Redis高阶之容错切换
当一台主机master宕掉之后,他的从机会取代主机么? 查看集群状态 127.0.0.1:6385> cluster nodes c8ff33e8da5fd8ef821c65974dda304d2e3327f9 192.168.58.129:638216382 slave f6b1fd5e58df90782f602b484c2011d52fc3482d 0 1733220836918 1 connecte…...
蓝桥杯准备训练(lesson2 ,c++)
3.1 字符型 char //character的缩写在键盘上可以敲出各种字符,如: a , q , , # 等,这些符号都被称为字符,字符是⽤单引号括 起来的,如: ‘a’ , ‘b’ &…...
【力扣】2094.找出3为偶数
思路 方法一:使用Set集合 1.首先是三层for循环,遍历,并且遇到不满足的情况,便跳过,继续计算。不如前导为0,以及遍历同一个数组下标的情况 2.使用Set集合来确保答案是唯一的,使用桶来标记也是可以的 3.但是…...
利用红黑树封装map,和set,实现主要功能
如果不知道红黑树是什么的时候可以去看看这个红黑树 思路 首先我们可以把封装分为两个层面理解,上层代码就是set,和map,底层就是红黑树 就相当于根据红黑树上面套了两个map,set的壳子,像下面这张图一样 对于map和set,map里面存…...
网络(TCP)
目录 TCP socket API 详解 套接字有哪些类型?socket有哪些类型? 图解TCP四次握手断开连接 图解TCP数据报结构以及三次握手(非常详细) socket缓冲区以及阻塞模式详解 再谈UDP和TCP bind(): 我们的程序中对myaddr参数是这样…...
CSS 选择器的优先级
一、基本概念 CSS 选择器的优先级决定了在样式冲突时,哪个样式规则将被应用到 HTML 元素上。通过理解 CSS 选择器的优先级,可以更好地控制网页元素的样式,避免样式冲突。 二、优先级计算规则 1. 内联样式 内联样式具有最高的优先级。 &l…...
留学生数学辅导作业随机过程高等线性代数概率论微积分优化统计
针对留学生数学辅导作业中的随机过程、高等线性代数、概率论、微积分、优化以及统计等科目,以下是一些详细的辅导建议和资源概述: 一、随机过程 概念理解: 随机过程是研究随机现象随时间演变的数学分支。它涉及概率论和数理统计的知识&#…...
移动机器人课程建图实验-ROSbug汇总
问题1描述 $ rosrun robot_state_publisher robot_state_publisher [ERROR] [1733131886.474757207]: [registerPublisher] Failed to contact master at [localhost:11311]. Retrying...解决方案 这个错误信息表明 robot_state_publisher 节点无法联系到 ROS master。通常&…...
小家电出海,沃丰科技助力保障售后服务的及时性与高效性
随着全球化步伐的加快,小家电行业也逐渐迈向国际市场,面向全球消费者提供服务。然而,跨国界的销售和服务挑战也随之而来,尤其是售后服务的及时性与高效性成为了企业亟需解决的问题。沃丰科技凭借其全渠道在线客服、工单系统和视频…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...
