C/C++语言基础知识 - 函数调用规则

引子

  • 一道比较常见的关于printf的笔试题
#include <stdio.h>  
  
void main() {  
    int i = 5;  
    printf("%d %d %d %d %d %d\n", i, --i, i--,i, i--,i);  
} 
* 求运行结果
在64位Ubuntu上的输出结果是      :2 2 4 2 5 2
在嵌入式平台ssc323上输出结果是  :2 2 4 2 3 2

原因

  • 这是由于函数调用规则不同导致的,函数调用对于程序员只是一条命令,但是语言实现却有一些需要考虑的,因此出现了多种调用规则。
  • 需要考虑的:
  1. 参数压栈顺序
  2. 栈维护
  3. 返回值存放
  4. 函数名称修饰

函数调用规则

  • 常见规则:stdcall、cdecl、fastcall、thiscall、naked call等。
调用规则__cdecl__stdcall__fastcall__pascal__thiscall
参数压栈顺序从右到左从右到左用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送从左到右从右到左
栈维护函数调用者函数本身函数本身函数本身函数本身
返回值存放EAXEAXEAXEAXEAX
C编译器名称修饰函数名前加上一个下划线前缀函数名前加上一个下划线前缀函数名前加上一个"@“符号,后面也是一个”@"符号和其参数的字节数
C++编译器名称修饰规则与_stdcall调用约定相同,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。见表下面规则与_stdcall调用约定相同,只是参数表的开始标识由上面的"@@YG"变为"@@YI"

获知当前编译工具使用的函数调用规则

  • 未找到方法,待研究

设置函数调用规则

  • 暂时找到类似方式,自测未生效,待研究
void fatal () __attribute__ ((stdcall__));
* 在头文件中可以
void fatal () __attribute__ ((__stdcall__));

个人总结

  • 以上函数调用规则的介绍在大多数博客中都能找到,规则种类较多,差别不大,看完好像并没有什么实际作用,在实际编程中,测试发现不同环境下的,语言并不是完全按照这些规则行事,例如:linux下,参数的压栈并不是完全按照从右到左或者从左到右,个人测试发现如果参数数据类型不同,编译器有时会自动调整顺序,个人更喜欢去测试和验证编译器的规则。

引子中例子的输出结果原因

  • 在64位Ubuntu和嵌入式平台ssc323上
  1. 函数调用参数压栈前,先会对所有参数进行运算,运算顺序:64位Ubuntu上是从右往左,ssc323平台是从左往右,可能是由压栈顺序决定的。
  2. 对于i–,会生成临时变量保存运算的结果,压栈也是使用的生成的临时变量。
  3. 对于–i,不会生成临时变量,经过了所有的参数运算后,最后压栈时使用的是变量i。
  • 64位Ubuntu上的压栈顺序(从右往左)
1. i, //所有参数运算完后,i值为2
2. i--, //从右往左运算,生成的临时变量值为5
3. i, //所有参数运算完后,i值为2
4. i--, //从右往左运算,生成的临时变量值为4
5. --i, //所有参数运算完后,i值为2
6. i //所有参数运算完后,i值为2
* 所以输出结果为:2 2 4 2 5 2 
* 结果的显示顺序还是从左到右,按代码需求来的,不会由于底层实现不同而发生变化。
  • 嵌入式平台ssc323上的压栈顺序(从左往右)
1. i, //所有参数运算完后,i值为2
2. --i, //所有参数运算完后,i值为2
3. i--, //从左往右运算,生成的临时变量值为4
4. i, //所有参数运算完后,i值为2
5. i--, //从左往右运算,生成的临时变量值为3
6. i //所有参数运算完后,i值为2
* 所以输出结果为:2 2 4 2 3 2
* 结果的显示顺序还是从左到右,按代码需求来的,不会由于底层实现不同而发生变化。
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C/C++语言程序开发开放参考手册的PDF版本是一本非常重要的参考书籍,它为C或C++语言编程提供了全面的指导和参考。这本手册通常包含了C或C++语言的各种语法规则、关键字、函数库、操作符和其他编程元素的详细解释和用法示例。 通过阅读这本开放参考手册,程序开发人员可以快速查找C/C++语言的相关信息和技巧,以帮助他们更高效地开发程序。手册中的内容包括但不限于:数据类型、控制结构、函数定义和调用、数组和指针、文件操作、内存管理等。 对于初学者来说,这本手册是学习C/C++语言的良好起点。它提供了简洁清晰的示例代码和解释,帮助读者理解各个概念和语法规则。通过阅读手册,初学者可以逐渐提升自己的编程能力,并掌握C/C++语言基础知识。 对于有经验的程序开发人员来说,这本手册可以作为日常工作中的参考书。无论是在解决问题、调试代码还是进行代码优化时,手册中的各种技术细节和用法示例都能提供帮助。通过查阅手册,程序开发人员可以更快地找到需要的信息,减少错误和不必要的麻烦。 总的来说,C/C++语言程序开发开放参考手册是程序开发人员必备的参考资料之一。它不仅在学习阶段提供了指导,还在实际编程中提供了技术支持。无论是初学者还是有经验的程序开发人员,都可以从中获得丰富的知识和指导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值