c中具有不同类型参数的可变函数

时间:2015-11-16 18:43:44

标签: c function variadic variadic-functions

我想知道在C中是否可以创建一个采用不同类型参数的可变函数。即。

void fillDatabase(char* name, int age){
  writeToDatabase(name, age);
}

int main(){
  fillDatabase("Paul", 19);
  fillDatabase("Herbert");
}

这里我试图填写一个包含姓名和年龄的数据库。但它也有可能只用一个名字填充它,没有年龄。所以我想知道我是否可以使用相同的功能,或者我必须写两个不同的功能?

Online我只能找到具有相同类型参数的可变函数的示例。

提前致谢!

2 个答案:

答案 0 :(得分:4)

在C99中,可变参数函数使用stdarg(3)操作(通常实现为扩展到编译器特定的神奇内容的宏,例如GCC内置函数)。第一个参数应该有一些固定的已知类型,并且通常确定如何获取其他参数;在今天的几个ABI中,可变参数传递不使用寄存器,因此效率低于固定的arity函数调用。

在你的情况下,你最好有几个功能。对于灵感,sqlite有several open functions

请注意,POSIX使用一个 last 可选参数定义了一些函数,特别是open(2)。这可能实现为具有不能提供 last 参数的函数。

您可以阅读ABI规范以及特定于您的实施的calling conventions

顺便说一句,缺乏函数重载(比如在C ++中)可以被理解为C的一个优点(函数名称 - linker唯一关心的事情,至少在Linux和Unix上确定 - 它的签名)。因此C ++实际上需要name mangling。另请阅读dynamic linkingdlopen

答案 1 :(得分:0)

查看va_list,va_start等的手册页

使用...序列表示函数原型来表示变量args:

void myfunction(FILE *, *fmt, ...);

例如,我们声明了一个va_list类型的结构(假设你包含了stdarg):

struct va_list l;

使用参数BEFORE初始化列表... - 我们将* fmt指针传递给va_start:

va_start(l, fmt);

现在,我们可以调用va_arg来获取值...如果我们正在处理格式字符串,我们可能会有这样的循环:

while (*fmt) {
    /* Look for % format specifier... */
    if (*fmt == '%') {
        /* Following character can be c for char, i for int or f for float. */
        // Opps - advance to char following opening %...
        fmt++;

        if (*fmt == 'c')
            fprintf(stream, "%c", (char) va_arg(l, int));
        else if (*fmt == 'i')
            fprintf(stream, "%i", (int) va_arg(l, int));
        else if (*fmt == 'f')
            fprintf(stream, "%f", (float) va_arg(l, double));
        ... and so on...

您依靠%后面的字符来告诉您相应参数中预期的数据类型。建议你阅读va_list的手册页。