函数参数深度剖析

1 函数参数的本质

1.1 函数参数的本质

函数参数的本质如下:

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

2 函数参数的求值顺序

2.1 顺序点的概念

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

程序中的顺序点:

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

C语言中的顺序点:

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

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

编程实验:程序中的顺序点
#include <stdio.h>

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。

在这里插入图片描述


参考资料:

  1. C语言进阶剖析教程
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值