可变参数的函数

2023-10-11 21:03:31 浏览数 (2)

什么是可变参数函数

C语言允许定义参数数量可变的函数,这称为可变参数函数(variadic function)。这种函数需要固定数量的强制参数,后面是数量可变的可选参数。其中,强制参数必须至少一个,可选参数数量可变,类型可变,可选参数的数量由强制参数的值决定。 C 语言中最常用的可变参数函数例子是 printf()和 scanf()。这两个函数都有一个强制参数,即格式化字符串。格式化字符串中的转换修饰符决定了可选参数的数量和类型。 可变参数函数格式:int fun(int a,...)

可变参数函数的引入

我们可以先简单用我们已知的信息,构造一个累加函数(可变参数)

代码语言:javascript复制
int sum(int addnum,...)
{
int i =0;
int res = 0;
for(i;i<addnum;i  )
{
  res =??
}
}

大概就是这样子,但是有一个问题,可变参数没有参数名 我们又怎么通过代码来访问这些参数呢?

可变参数的获取

我先粘贴一下微软给我们的办法:

代码语言:javascript复制
当编写可变参数函数时,必须用 va_list 类型定义参数指针,以获取可选参数。可变参数函数要获取可选参数时,必须通过一个类型为 va_list 的对象来进行访问,它包含了参数信息。这种类型的对象也称为参数指针(argument pointer),它包含了栈中至少一个参数的位置。可以使用这个参数指针从一个可选参数移动到下一个可选参数,由此,函数就可以获取所有的可选参数。va_list 类型被定义在头文件 stdarg.h 中。

研究过堆栈的都知道参数也是会被压入堆栈中的,根据压入方式不同(涉及调用约定 我这里先不提)因为他是被按顺序压入的,我们只要通过va_list这个参数指针指向已经存在的最后一个强制参数,通过移动指针就可以访问到可变参数,这里简单说明一下,后面我会说明函数的调用约定。 现在引入两个函数实现上面的想法: void va_start(va_list argptr, lastparam); 该函数的第一个参数是一个va_list 类型的指针,第二个参数是可变参数函数中最后一个强制参数,即第一个可选参数前的强制参数。实现了指针指向最后一个强制参数,该函数会初始化指针argptr type va_arg(va_list argptr, type); 其第一个参数是已经初始化完成的va_list指针,第二个参数则为可变参数的类型,返回的参数就是当前va_list指针所指的可变参数,所以类型也跟传入的可变参数类型相同。访问完一个可变参数会后移指向下一个可变参数 va_end 当不再需要使用参数指针时,必须调用宏 va_end。如果想使用宏 va_start 或者宏 va_copy 来重新初始化一个之前用过的参数指针,也必须先调用宏 va_end。 代码示例:

代码语言:javascript复制
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
int sum(int n, ...)
{
    int i = 0;
    int res = 0;
    va_list arg;
    va_start(arg, n);
    for (size_t i = 0; i < n; i  )
    {
        res  = va_arg(arg, int);
    }
    va_end(arg);
    return res;

}
int main()
{
    int addsum = 0;
    addsum = sum(5, 2, 3, 4, 5, 6);
    printf("%dn", addsum);
}

上述方法不能智能识别不同参数的个数和类型。

如果想实现智能识别可变参数,比如printf,需要在自己的程序中作特殊处理 具体方法我这里就不介绍了,以后遇到会单独写一篇文章。 感兴趣的可以看一下这篇文章:https://blog.csdn.net/xiaolong_lili/article/details/114708390 明白数据在内存中的存储很容易理解。

0 人点赞