函数参数深度剖析
发布日期:2021-07-01 04:24:24 浏览次数:2 分类:技术文章

本文共 1184 字,大约阅读时间需要 3 分钟。

文章目录

1 函数参数的本质

1.1 函数参数的本质

函数参数的本质如下:

  • 函数参数在本质上与局部变量相同在栈上分配空间。
  • 函数参数的初始值是函数调用时的实参值。
    在这里插入图片描述

2 函数参数的求值顺序

2.1 顺序点的概念

顺序点是C语言中变量修改的最晚时机。

程序中的顺序点:

  • 程序中存在一定的顺序点。
  • 顺序点指的是执行过程中修改变量值的最晚时刻。
  • 在程序到达顺序点的时候,之前所做的一切内存操作必须完成。

C语言中的顺序点:

  • 每个完整表达式结束时,即分号处。
  • &&,||,?:以及逗号表达式的每个参数计算后。
  • 函数调用时所有实参求值完成后(进入函数体之前)。

在这里插入图片描述

输出结果:6(gcc、bcc、vc)
分析:首先将k的值取道寄存器中去,然后再从内存中把k的值取出来和寄存器中的值进行相加,将值保存到k中去,此时悬挂了两个++操作。然后进行两次++操作,所以此时的k为6。

编程实验:程序中的顺序点#include 
int main(){
int k = 2; int a = 1; k = k++ + k++; printf("k = %d\n", k); // 6 if( a-- && a ) {
printf("a = %d\n", a); // 不打印 } return 0;}

2.2 函数参数的求值顺序分析

函数参数的求值顺序依赖于编译器的实现。

在这里插入图片描述
gcc: 2 1 3(最后一个为k的值)
bcc:2 1 3
vc: 1 1 3(跟顺序点有关,假设从第二个参数开始求值,首先从内存中取出k的值为1,此时的++操作并没有进,而是处于悬挂状态,所以第二个参数的值为1。然后对第一个参数进行求值,从内存中取出k的值为1,++操作仍然悬挂着,所以此时第一个参数的值也为1。由于顺序点存在于函数调用时所有实参求值完成后,即进入函数体前,所以此时必须进行修改内存的操作,执行两个++操作,使得此时的k的值变成了3)。

注意:C语言中只规定了必须将参数的值计算出来再进行函数调用,并没有规定参数的求值顺序。可类比到操作符中,操作符的求值顺序也是不固定的,依赖于编译器的实现。


3 函数参数的入栈顺序

3.1 调用约定

当函数调用发生时:

  • 参数会传递给被调用的函数。
  • 而返回值会被返回给函数调用者。

调用约定描述参数如何传递到栈中以及栈的维护方式:

  • 参数传递顺序。
  • 调用栈清理。

当主函数调用第三方库时,需要考虑调用约定是否一致。

关于调用约定:

  • 调用约定是预定义的,可理解为调用协议。
  • 调用约定通常用于库调用和库开发的时候:
    • 从右到左依次入栈:_stdcall,_cdecl(C语言默认是这个),_thiscall;
    • 从左到右依次入栈:_pascal, _fastcall。

在这里插入图片描述


参考资料:

转载地址:https://muzimin.blog.csdn.net/article/details/104004311 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:函数中的可变参数
下一篇:函数的意义

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年05月05日 10时38分54秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章