函数调用的区别:_cdecl以及_stdcall

群晖NAS实战:从零部署Container Manager与Docker代理配置全攻略 本文详细介绍了在群晖NAS上从零部署Container Manager与配置Docker代理的完整流程。针对国内用户常见的镜像拉取问题,提供了图形化界面与SSH命令行两种解决方案,并分享了MySQL容器部署的实战案例。文章特别强调了网络配置技巧和日常维护方法,帮助用户高效管理NAS上的容器应用。 阅读详情

一、概念
1)_stdcall调用
_stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,由调用者完成压栈操作,被调函数自身在返回前清空堆栈。
WIN32 Api都采用_stdcall调用方式,这样的宏定义说明了问题: #define WINAPI _stdcall

按C编译方式,_stdcall调用约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数,形如_functionname@number.
Therefore, the function declared as int func( int a, double b ) is decorated as follows: _func@12.
按C++编译方式,可参看(三)

2)_cdecl调用
_cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式,由调用者完成压栈操作 ,传送参数的内存栈由调用者维护。
_cedcl约定的函数只能被C/C++调用
,每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。
按C编译方式,_cdecl调用约定仅在输出函数名前面加下划线,形如_functionname。
按C++编译方式,可参看(三)

二、区别
几乎我们写的每一个WINDOWS API函数都是__stdcall类型的,首先,需要了解两者之间的区别: WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除?如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。那么为什么还需要_cdecl呢?当我们遇到这样的函数如 fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用 _cdecl。到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字。

三、编译时函数名修饰约定规则
1)首先介绍一下函数修饰名,C” 或者“C++”函数在内部(编译和链接)通过修饰名识别。修饰名是编译器在编译函数定义或者原型时生成的字符串。有些情况下使用函数的修饰名是必要的,如在模块定义文件里头指定输出“C++”重载函数、构造函数、析构函数,又如在汇编代码里调用“C””或“C++”函数等。修饰名由函数名、类名、调用约定、返回类型、参数等共同决定。名字修饰约定随调用约定和编译种类(C或C++)的不同而变化。函数名修饰约定随编译种类和调用约定的不同而不同。下面详细说明在C++编译器中修饰名的约定方法,在C编译器中的变化已经在(一)中阐述。

2)C++编译时函数名修饰约定规则
  __stdcall调用约定:
  1)、以"?"标识函数名的开始,后跟函数名;
  2)、函数名后面以"@@YG"标识参数表的开始,后跟参数表;
  3)、参数表以代号表示:
  X--void ,
  D--char,
  E--unsigned char,
  F--short,
  H--int,
  I--unsigned int,
  J--long,
  K--unsigned long,
  M--float,
  N--double,
  _N--bool,
  PA--表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以"0"代替,一个"0"代表一次重复;
  4)、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;
  5)、参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。
  其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ",例如   int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z”   void Test2() -----“?Test2@@YGXXZ”
  __cdecl调用约定:
  规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。

四、在C++编译时,引入c库里面的函数的处理
如果Add(int a, int b)是在c语言编译器编译,而在c++文件使用,由(三)知,因为c编译器和c++编译器对函数名的解释不一样(c++编译器解释函数名的时候要考虑函数参数,这样是了方便函数重载,而在c语言中不存在函数重载的问题),会出现链接错误。 哪么该如何处理呢?这是关键字extern就派上用场了。
而在c++文件使用c编译器编译过的函数,则需要在c++文件中声明:extern "C" Add(int a, int b),使用extern "C",实质就是告诉c++编译器,该函数是c库里面的函数。请保持我的名称,不要给我生成用于链接的函数修饰名。
另外顺便说一下extern的另一个用途,extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。#inlcude "***.***" 和 int f() 等价于 extern int f() ;即 extern 申明的函数前不需要加引用头文件就能用。

参考文献:
博客:http://www.cnblogs.com/Winston/archive/2008/09/11/1289391.html

智能手表PCB布局:PPG与IMU传感器噪声隔离与应力解耦设计 在可穿戴设备硬件开发中,PCB布局已超越传统布线范畴,成为决定信号完整性、电磁兼容性与机械可靠性的核心环节。心率传感器(PPG)依赖微伏级光电容积脉搏波信号,极易受数字开关噪声与电源纹波干扰;姿态传感器(IMU)则对PCB弯曲形变引发的机械应力高度敏感。其布局需融合电磁场建模、热-力-电多物理协同及高密度互连约束。关键技术价值体现在噪声路径切断、地弹抑制、应力方向解耦与电源域隔离等工程实践。典型应用场景涵盖智能手表、医疗级贴片设备及微型运动传感终端。本文聚焦PPG与IMU两大模组在STM32L4平台上的实操 阅读详情

相关推荐

从编解码芯片看Tesla T4的隐藏实力:双NVDEC如何实现70路1080P解码?

本文深入剖析了英伟达Tesla T4显卡的隐藏实力,重点解读其独特的双NVDEC硬件解码器设计如何突破性能瓶颈。通过分析Turing架构、对比HEVC/H.264解码差异,并结合驱动与SDK优化,揭示了实现高达70路1080P视频流并发解码的原理与实战配置,为云游戏、直播转码等高并发场景提供高效解决方案。

weixin_29209801的博客 487

_stdcall 调用类型 函数参数压栈方式为什么是从右到左的?

据说是为了支持可变长参数 比如printf("%s%d%d\n", s, a, b); 格式字符串是确定存在的,其他的都是不确定的。 格式字符串最后一个入栈,位于栈顶,第一个出栈,这样就很方便。 函数调用的区别:_cdecl以及_stdcall 一、概念 1)_stdcall调用    _stdcall是Pascal程序的缺省调用方式,参数采用从

qq_31209383的博客 1422

神经网络基础-从零开始搭建一个神经网络

人工神经网络(Articial Neural Network,简写为ANN)也称为神经网络(NN),是一种模仿生物神经网络和功能的计算模型,人脑可以看做是一个生物神经网络,由众多的神经元连接而成,各个神经元传递复杂的电信号,树突接收到输入信号,然后对信号进行处理,通过轴突输出信号。人工神经网络也是类似,通过模仿人脑的“学习机器”,通过不断“看”数据(比如图片,数字),自己总结规律,最终学会预测(比如分类图片)在深度学习中,损失函数是用来衡量模型参数的质量的函数,衡量的方式是比较网络输出和真实输出的差异。

Zach的博客 4014

warning: function declared implicitly错误原因

http://blog.sina.com.cn/s/blog_629f56a70100irbn.html line 10: warning: function declared implicitly 这是由于没有声明函数原型造成的。 在a.c中, void main() { ..... delay(); .... } 在b.c中 void delay() { } 如果就

worf1234的专栏 8730

OpenSpec 从入门到精通:AI 时代的最佳 SDD 范式

同样都是「先写规范再写代码」的开源 SDD 框架,OpenSpec(https://github.com/fission-ai/openspec) 展现出了极高的工程性价比,无论是使用 Claude Code、Cursor 还是 Aider,都可以无缝接入 OpenSpec 的规格管理层。这些问题需要人来做判断,AI 做不了这个主。整个流程跑下来,OpenSpec 产出的效果还是令人满意的,一些前期没有考虑到的细节 AI 都补上了,生成的相关文档也有利于开发人员的知识对齐,可以尝试在团队内部推广。

qq_39093474的博客 933

宝塔面板一键部署Z-Blog博客 - 内网穿透实现公网访问

Ubuntu系统作为Linux系统的一个重要分支,既有Linux系统的轻量化、高扩展性和长时间稳定运行,也拥有Windows一样的友好图形界面,因此可以作为熟悉服务器系统的良好选择。对于笔者来说,ubuntu系统最大的用处,就是可以让家里老旧的电脑重焕生机,让本已退居二线的电脑与cpolar内网穿透软件搭配,成为私人服务器,搭建自己喜欢的各种网站。今天,笔者就为大家介绍,如何使用cpolar内网穿透+Z-blog搭建私人博客网站。

m0_74808907的博客 3147

__cdecl __stdcall各种调用约定详解

<br />调用协定(Calling Conventions)详解<br />资料收集:heartfly<br />学习时间:2010-10-11<br />what are the calling conventions? When a function is called, the arguments are typically passed to it, and the return value is retrieved. A calling convention describes how the

逆风飞扬 1857

大疆上云API-1.10.0版本-设备位置数据实时处理与WebSocket推送实战解析

本文深入解析了大疆上云API 1.10.0版本中设备位置数据的实时处理与推送全链路。通过剖析源码,详细阐述了从MQTT接收OSD数据、Spring Integration路由分发、业务逻辑处理到WebSocket实时推送至前端地图的核心流程,并提供了实战优化与避坑指南,帮助开发者构建高可靠的无人机实时定位系统。

weixin_29291863的博客 413

转:函数调用的区别:_cdecl以及_stdcall

函数调用的几个概念:_stdcall,_cdecl.... 1、_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。 2、C调用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出...

diaomo9737的博客 157

Arduino与Proteus仿真实例-HG7881(L9110)驱动直流电机仿真

HG7881(L9110)驱动直流电机仿真 HG7881 (L9110) 双通道电机驱动器模块。 HG7881 (L9110) 是一款紧凑型电机驱动芯片,支持 2.5-12V 电压范围,800mA 连续电流。 这些芯片具有内置输出钳位二极管以保护敏感的微控制器电子设备。 它们适用于非常小的机器人项目。 每个 HG7881 (L9110) 芯片都能够使用两个数字控制输入驱动单个直流电机。 一个输入用于选择电机方向,而另一个用于控制电机速度。 速度是通过使用 PWM 脉冲宽度调制来控制的。 电机驱动器通常具有

视觉与物联智能 3051

【HFSS】仿真目录

Author: JiJi\textrm{Author: JiJi}Author: JiJi Created Time: 2026.04.27\textrm{Created Time: 2026.04.27}Created Time: 2026.04.27 Modified Time: 2026.04.27\textrm{Modified Time: 2026.04.27}Modified Time: 2026.04.27如果大家觉得有用,就点个赞吧,在阅读过程中存在任何困惑,可在下方评论区留言~

u011699626的博客 311

JNA函数调用约定终极指南:StdCall与Cdecl的区别及应用

Java Native Access(JNA)是一个强大的Java库,它让Java程序能够轻松访问本地共享库,而无需编写JNI或本地代码。在使用JNA进行Java与本地库交互时,**函数调用约定**是一个至关重要的概念,特别是StdCall和Cdecl这两种最常见的调用约定。理解它们的区别对于正确使用JNA至关重要。 ## 🔍 什么是函数调用约定? 函数调用约定定义了函数调用过程中参数传递、

gitblog_00010的博客 1003

向华为学习——IPD流程体系之IPD术语

《IPD体系核心概念与业务术语解析》摘要: IPD(集成产品开发)是一种以市场为导向的结构化产品开发管理模式,通过跨部门协作、异步开发、CBB(通用构建模块)和管道管理等手段,实现产品全生命周期高效管理。体系包含七大核心要素:跨部门团队(如IPMT决策层、PDT执行层)、结构化流程(分阶段评审)、端到端项目管理(WBS分级计划)、客户需求分析、投资组合优化及质量管控(TR技术评审)。各业务领域术语涵盖财务(NPV、IRR)、开发(需求分解、基线化)、制造(可制造性设计)、采购(Sourcing团队)及市场(

cdfunlove的博客 482

深入理解函数调用约定:stdcall、cdecl、fastcall、thiscall 的区别与应用

在C/C++开发中,函数调用约定(Calling Convention)决定了函数参数如何传递、栈空间由谁清理、函数名修饰规则等底层细节。:由调用者(Caller)还是被调用函数(Callee)清理栈。:在逆向工程中,识别调用约定可帮助理解参数传递和栈平衡逻辑。略优,因为栈清理只需一次(在函数内部),但差异通常可以忽略。参数从右到左压栈(MSVC)或寄存器优先(GCC)。:不同编译器对调用约定的名称修饰规则不同(如。C/C++默认调用约定(非类成员函数)。A:确保调用约定一致,否则会导致栈错误。

@ 1152

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

上一篇: 采用D3DXCreateTextureFromFileEx读取Cubemap贴图时候的问题
下一篇: 函数调用的区别:_cdecl以及_stdcall
rootvy
博客等级 码龄21年 2粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值