函数参数(可变参数)

函数参数

  • 函数参数在本质上和局部变量相同在栈上分配空间
  • 函数参数的初始值是函数调用时的实参值
  • 函数参数的求值顺序依赖于编译器的实现
int k = 1;
printf("%d, %d \n",k++,K++);
//gcc 编译器输出 2,1
//这个是不确定的

顺序点

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

  • &&,||,?:和逗号表达式的每个参数计算后

int k = 2;
k = k++ + k++;
// 6
  • 函数调用时所有实参求值完成后
void f()
{
    printf("%d %d \n",i,j);
}

int main()
{
    int k =1;
    f(k++,k++);// 1 1 or 2 1  这是不固定的,避免这样写程序
    printf("%d",k);//3
    return 0;
}

参数入栈的顺序

调用约定
  • 当函数调用发生时。参数会被传递给调用的函数,而返回值会被返回给函数调用者
  • 调用约定描述参数如何传递到栈中以及栈的维护(参数传递顺序,调用栈清理)
  • 调用约定是预定义的可理解为调用协议
  • 调用约定通常用于库调用和库开发的时候

    从右到左依次入栈: _stdcall , _cdecl , _thiscall
    从左到右依次入栈: _pascall , _fastcall


==当调用第三方库的时候,可能库文件的入栈顺序和当前语言不一样,这时候就需要指定入栈次序了==

可变参数

  • C语言中可以定义参数可变的函数
  • 需要包含 stdarg.h 头文件

    va_list 参数集合
    va_arg 取具体参数值
    va_start 标识参数访问的开始
    va_end 标识参数访问的结束

  • 示例程序

#include <stdio.h>
#include <stdarg.h>

float average(int n, ...)
{
    va_list args;
    int i = 0;
    float sum = 0;

    va_start(args, n);

    for(i=0; i<n; i++)
    {
        sum += va_arg(args, int);
    }

    va_end(args);

    return sum / n;
}

int main()
{
    printf("%f\n", average(5, 1, 2, 3, 4, 5));
    printf("%f\n", average(4, 1, 2, 3, 4));

    return 0;
}

可变参数的限制


  • 可变参数必须从头到尾按照顺序逐个访问
  • 参数列至少要存在一个确定的命令参数
  • 可变参数函数无法确定实际存在的参数的数量
  • 可变参数函数无法确定参数的实际类型

va_arg中如果指定了错误的类型,那么结果是不可预料的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值