在c中传递不同类型的可变数量的参数

时间:2017-10-03 14:43:44

标签: c

我想创建一个函数,它将采用不同类型的可变数量的参数。我的问题是如何解析参数类型。像调用者可以按任何顺序传递任何类型的参数(不指定格式说明符)。所以在调用函数中,我如何区分类型。

如何在函数var_argument中打印调用者传递的所有值?

假设我想在调用者传递的参数的var_argument函数内做sprintf

这是我的C代码

#include <stdio.h>
#include <stdarg.h>
void var_argument(int num,...);

int main()
{
 var_argument(3,"Hello",7.87f,6);
 var_argument(3,7.87f,"Hello",6);
 return 0;
}

void var_argument(int num,...)
{
 char str[80];
/* What code should I write to differentiate between types and to print all the values passed by the caller */     

 va_list list;
 va_start(list,num);

 /* How to do sprintf of the parameter passed to this function and store 
 the formatted output in the array str  */
}

1 个答案:

答案 0 :(得分:2)

这已经以某种方式完成了,例如printf()有这样的机制。对于变量参数函数,您需要一个不属于变量参数的第一个参数,将其用作格式字符串以确定 n 位置的参数 x 的类型。

因为第一个参数是必需的,所以你必须有这样一个参数,并且将它用作变量参数中预期的指示似乎很自然。

以此为例,

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

int
variable(const char *format, ...)
{
    va_list args;
    int count;

    va_start(args, format);

    count = 0;
    while (*format != '\0') {
        switch (*format++) {
            case 's':
                fprintf(stdout, "arg[%d]: %s\n", count, va_arg(args, const char *));
                break;
            case 'd':
                fprintf(stdout, "arg[%d]: %d\n", count, va_arg(args, int));
                break;
            case 'f':
                fprintf(stdout, "arg[%d]: %f\n", count, va_arg(args, double));
                break;
        }
        count += 1;
    }
    va_end(args);
    return 0;
}

int
main(void)
{
    variable("sdf", "Example", 3, 3.1416);
}

当然,说明符与参数的实际类型之间的任何不匹配都将导致未定义的行为,并导致不良行为的逻辑结果。所以你必须非常小心,或者使用printf()样式说明符并告诉编译器警告是否发生这种不匹配。

另一个解决方案就是像 glib 的一些函数那样做,传递一个类型说明符并紧接在参数之后,用最后一个值来表示参数的结束。参数&#34; 说明符&#34;可以是enum枚举所有支持的类型,例如

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

enum types {
    String, Integer, Double, Float = Double, /* unless you want to store the value in a poitner
                                              * there is normally no difference between these
                                              */
    End
};

int
variable(enum types type, ...)
{
    va_list args;
    int count;

    va_start(args, type);

    count = 0;
    while (type != End) {
        switch (type) {
            case String:
                fprintf(stdout, "arg[%d]: %s\n", count, va_arg(args, const char *));
                break;
            case Integer:
                fprintf(stdout, "arg[%d]: %d\n", count, va_arg(args, int));
                break;
            case Double:
                fprintf(stdout, "arg[%d]: %f\n", count, va_arg(args, double));
                break;
            default:
                fprintf(stderr, "unknown type specifier\n");
                break;
        }
        type = va_arg(args, enum types);
        count += 1;
    }

    va_end(args);
    return 0;
}

int
main(void)
{
    variable(String, "Example", Integer, 3, Double, 3.1416, End);
}