C语言中可变参函数介绍与示例

本文主要介绍C语言中可变参函数的相关内容,以及展示几个简单的可变参函数功能的示例。

1. 可变参函数的概念

在使用C语言编程的时候,函数中形式参数的数目通常是确定的,在调用时要依次给出与形式参数对应的所有实际参数,但在某些情况下,我们希望函数的参数个数可以根据需要来确定(例如常见的printf()函数,它的函数参数个数就是不确定的),这时我们就需要可变参函数了。

采用 ANSI 标准形式时,可变参函数的原型声明如下:

type funcname(type para1, type para2, ...)

上述函数定义形式至少需要一个普通的形式参数,后面的省略是函数原型的一部分,表示该函数为可变参函数,type是函数返回值和形参的类型。

注意:函数参数表中的三个圆点只能放在参数表最后,即在所有普通参数之后。

2. 用法

为了能在可变参函数里取得并处理不定个数的“其他参数”,需要使用头文件<stdarg.h>提供的一套机制。

头文件<stdarg.h>提供了一个特殊类型va_list,在每个可变参函数的函数体里必须定义一个va_list类型的局部变量,它将成为访问由三个圆点所代表的实际参数的媒介。

下面假设某个可变参函数里所用的va_list类型的变量的名字是vap,我们使用vap访问实参的步骤大致如下:

1)在使用vap访问实际参数之前,必须先用宏va_start对这个变量初始化,如下:

va_start(vap, nNum);

nNum是可变参函数的最后一个确定的参数,va_start使vap指向第一个可选参数。

2)然后使用va_arg宏返回参数列表中的当前参数,并使vap指向参数列表中的下一个参数,如下:

va_arg(vap, int);

在调用宏va_arg时必须提供有关实参的实际类型(如本例中的int),这一类型也将成为这个宏调用的返回值类型。

3)在使用va_arg宏获取了所有的实参之后,最后使用va_end宏把vap指针清为NULL,如下:

va_end(vap);

我们在函数体内可以多次遍历这些由vap代表的实参,但是都必须以va_start开始,并以va_end结尾。

3. demo演示

3.1 demo1

需求:我们想定义一个函数sum,该函数可以有任意多个整型参数,函数sum最终返回这些参数的和。

我们应该将sum函数定义为一个只有一个普通参数、并具有可变长度参数表的函数,这个函数的头部应该是(函数原型与此类似):

int sum(int n, ...)

实际上我们要求在调用该函数时,第一个参数n代表想要求和的参数个数,而其余的参数为将要进行求和的参数。

完整代码(variable_arg.c)如下:

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

int sum(int nNum, ...)
{
    va_list vap;
    int nSum = 0;
    int i;

    va_start(vap, nNum);
    for (i = 0; i < nNum; i++)
    {
        nSum += va_arg(vap, int);
    }
    va_end(vap);

    return nSum;
}

int main()
{
    int nSumValue = 0;

    nSumValue = sum(3, 10, 11, 19);

    printf("nSumValue is: %d\n", nSumValue);

    return 0;
}

编译后,运行该程序,运行结果如下:


上述结果显示可变参函数sum满足了我们的需求。

3.2 demo2

需求:使用可变参函数,将可变个数的字符串参数打印出来。

我们应该将demo函数定义为一个只有一个普通参数、并具有可变长度参数表的函数,这个函数的头部应该是(函数原型与此类似):

int demo(char* msg, ...)
我们在调用该函数时,会将除msg外的其余的参数打印出来,同时需要注意, 在实际调用这个函数时,要通过一定的方法指明实际参数的个数,例如把最后一个参数置为空字符串(本例采用此种方式)或其他的方式。

完整代码(variable_arg2.c)如下:

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

/* 函数原型声明,至少需要一个确定的参数,注意括号内的省略号*/
int demo(char*, ...);

int main()
{
    demo("DEMO", "This", "is", "a", "demo!", "");
}

/* ANSI标准形式的声明方式,括号内的省略号表示可选参数 */
int demo(char *msg, ...)
{
    /* 定义保存函数参数的结构 */
    va_list argp;

    /* 记录参数个数 */
    int argno = 0; 
    /* 存放取出的字符串参数*/
    char *para;

    /* argp指向传入的第一个可选参数,msg是最后一个确定的参数 */
    va_start(argp, msg);

    while (1)
    {
        /* 取出当前的参数,类型为char* */
        para = va_arg(argp, char*);
        /* 采用空串指示参数输入结束 */
        if (strcmp("", para) == 0)
        {
            break;
        }
        
        printf("Parameter #%d is: %s\n", argno, para);
        argno++;
    }
    
    /* 将argp置为NULL */
    va_end(argp); 
    
    return 0;
}

编译后,运行该程序,运行结果如下:


上述结果显示可变参函数demo满足了我们的需求。


猜你喜欢

转载自blog.csdn.net/liitdar/article/details/80230741