C语言中如果参数个数不定,可以用省略号传参

var func(parm_list, ...)

printf 也是用了这种传参方式。
函数传参的时候用到了栈的数据结构,参数从右往左一个一个入栈。所以理论上,知道一个参数的类型和其中一个的地址,就可以知道所有参数。

//var_list 是char*类型,定义一个var_list
var_list args;
//var_list 初始化
var_start(args, parm_list);
//调用var_arg ,返回type类型变量
var_arg(args, type);
//获取所有参数之后,以防发生危险,需要把args指针置为NULL
var_end(args);

可以看一个简单printf的例子

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

void myprintf(const char *format, ...)
{
     va_list ap;
     char c;

     va_start(ap, format);
     while (c = *format++) {
      switch(c) {
      case 'c': {
           /* char is promoted to int when passed through '...' */
           char ch = va_arg(ap, int);
           putchar(ch);
           break;
      }
      case 's': {
           char *p = va_arg(ap, char *);
           fputs(p, stdout);
           break;
      }
      default:
           putchar(c);
      }
     }
     va_end(ap);
}

int main(void)
{
     myprintf("c\ts\n", '1', "hello");
     return 0;
}