- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
C语言中函数参数入栈的顺序
先通过一个小程序来看一看:
#include
void foo(int x, int y, int z)
{
printf(x = %d at [%X]n, x, x);
printf(y = %d at [%X]n, y, y);
printf(z = %d at [%X]n, z, z);
}
int main(int argc, char *argv[])
{
foo(100, 200, 300);
return 0;
}
运行结果:
x = 100 at [BFE28760]
y = 200 at [BFE28764]
z = 300 at [BFE28768]
?
C程序栈底为高地址,栈顶为低地址,因此上面的实例可以说明函数参数入栈顺序的确是从右至左的。可到底为什么呢?查了一直些文献得知,参数入栈顺序是和具体编译器实现相关的。比如,Pascal语言中参数就是从左到右入栈的,有些语言中还可以通过修饰符进行指定,如Visual C++.即然两种方式都可以,为什么C语言要选择从右至左呢?
进一步发现,Pascal语言不支持可变长参数,而C语言支持这种特色,正是这个原因使得C语言函数参数入栈顺序为从右至左。具体原因为:C方式参数入栈顺序(从右至左)的好处就是可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反。
因此,C语言函数参数采用自右向左的入栈顺序,主要原因是为了支持可变长参数形式。换句话说,如果不支持这个特色,C语言完全和Pascal一样,采用自左向右的参数入栈方式。
?
这儿其实还涉及到C语言中调用约定所采用的方式,下面简单的介绍一下:
__stdcall与C调用约定(__cdecl)的区别
?
C调用约定在返回前,要作一次堆栈平衡,也就是参数入栈了多少字节,就要弹出来多少字节.这样很安全.
有一点需要注意:stdcall调用约定如果采用了不定参数,即VARARG的话,则和C调用约定一样,要由调用者来作堆栈平衡.
(1)_stdcall是Pascal方式清理C方式压栈,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上@和参数的字节数。 int f(void *p) -- _f@4(在外部汇编语言里可以用这个名字引用这个函数)
在WIN32 API中,只有少数几个函数,如wspintf函数是采用C调用约定,其他都是stdcall
(2)C调用约定(即用__cdecl关键字说明)(The C default calling convention)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数vararg的函数(如printf)只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。 _cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀。
(3)__fastcall调用的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈),在函数名修饰约定方面,它和前两者均不同。__fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上@前缀,在函数名后加上@和参数的字节数。
(4)thiscall仅仅应用于C++成员函数。this指针存放于CX/ECX寄存器中,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。
(5)naked call。 当采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。
(这些代码称作 prolog and epilog code,一般,ebp,esp的保存是必须的).
但是naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。
关键字 __stdcall、__cdecl和__fastcall可以直接加在要输出的函数前。它们对应的命令行参数分别为/Gz、/Gd和/Gr。缺省状态为/Gd,即__cdecl。
要完全模仿PASCAL调用约定首先必须使用__stdca
您可能关注的文档
- AppleID被盗后的惊魂50小时.doc
- APP产品用户体系建设初步研究及见解.doc
- ARCGIS不懂编程也可以批量生成数据文件.doc
- ArcielArdor附属小册子.doc
- ARCGIS9.3软件安装手册2015.doc
- ASU-Intro081126阿肯色州立.doc
- AT89C51的概况.doc
- ATN-300型全自动定氮仪-操作手册.doc
- ATX电源功率几何.doc
- Authorware7.0与Access数据库连接实例(上).doc
- 2025安徽淮南市纪委监委面向市直机关选调12人备考题库附答案解析.docx
- 2025湖南岳阳市口岸事务中心选调1人行测备考题库附答案.docx
- 2025广东梅州市平远县选调县委组织部人员2人行测备考题库附答案.docx
- 2025教育部教育管理信息中心招聘2人(第二批)(非事业编制)备考题库附答案解析.docx
- 2025四川省经济和信息化厅所属事业单位选调工作人员22人行测备考题库附答案.docx
- 2025四川省市场监督管理局所属事业单位补充选调13人备考题库附答案解析.docx
- 宜宾市宜宾县2022-2023学年数学四年级第一学期期末质量检测模拟测试题(含解析).pdf
- 2025甘肃张掖市阳光人寿保险股份有限公司招聘12人笔试备考试题附答案解析.docx
- 2025广东南粤银行肇庆分行招聘备考题库附答案.docx
- 2026年洛阳汝阳县人力资源和社会保障局公开招聘乡村公益性岗位人员132名备考题库附答案解析.docx
最近下载
- 2024-2030年中国白羽鸡行业发展潜力及投资价值研究报告.docx
- DB51_T5058-2020:四川省抗震设防超限高层民用建筑工程界定标准.pdf VIP
- 腰椎间盘突出症医学课件.ppt VIP
- 腰椎间盘突出症医学课件.ppt VIP
- 电动汽车充电策略动态优化模型及仿真分析.docx VIP
- Q-CR9149-2018铁路大型临时工程和过渡工程设计规范(附条文).pdf VIP
- 《地理信息系统导论》复习资料(要点).pdf VIP
- 2024年天津市河东区中考英语模拟试卷(3月份)(含详细答案解析).docx VIP
- 《功能型无人车通用技术条件》.pdf VIP
- 机械维修的主要事迹范文(共10篇).pdf VIP
原创力文档


文档评论(0)