首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Variadic arguments

变量函数是可以用不同数量的参数调用的函数。

只有新式(原型)函数声明可能是可变的。这由...必须出现在参数列表中的最后一个格式的参数表示,并且必须至少跟随一个命名参数。

代码语言:javascript
复制
//New-style declaration
int printx(const char* fmt, ...); // function declared this way
printx("hello world"); // may be called with one
printx("a=%d b=%d", a, b); // or more arguments
 
// int printy(..., const char* fmt); // Error: ... must be the last
// int printz(...); // Error: ... must follow at least one named parameter

在函数调用中,作为变量参数列表一部分的每个参数都会经历特殊的隐式转换,称为默认参数促销。

在使用可变参数的函数体内,可以使用<stdarg.h>库函数来访问这些参数的值:

| Defined in header <stdarg.h> |

|:----|

| va_start | 允许访问可变参数函数参数(函数宏)|

| va_arg | 访问下一个可变参数函数参数(函数宏)|

| va_copy(C99)| 制作可变参数函数参数(函数宏)|的副本

| va_end | 结束可变参数函数参数(函数宏)|的遍历

| va_list | 保存va_start,va_arg,va_end和va_copy(typedef)所需的信息|

注释

虽然旧式(无原型)函数声明允许后续函数调用使用任意数量的参数,但它们不允许为可变参数(从C89开始)。这种函数的定义必须指定一个固定数量的参数,并且不能使用这些stdarg.h宏。

代码语言:javascript
复制
//old-style declaration
int printx(); // function declared this way
printx("hello world"); // may be called with one
printx("a=%d b=%d", a, b); // or more arguments
// the behavior of one of these calls is undefined, depending on
// whether the function is defined to take 1 or 3 parameters

代码语言:javascript
复制
#include <stdio.h>
#include <time.h>
#include <stdarg.h>
 
void tlog(const char* fmt,...)
{
    char msg[50];
    strftime(msg, sizeof msg, "%T", localtime(&(time_t){time(NULL)}));
    printf("[%s] ", msg);
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}
 
int main(void)
{
   tlog("logging %d %d %d...\n", 1, 2, 3);
}

输出:

代码语言:javascript
复制
[10:21:38] logging 1 2 3...

参考

  • C11标准(ISO / IEC 9899:2011):
    • 6.7.6.3/9函数声明符(包括原型)(p:133)
    • 7.16变量参数<stdarg.h>(p:269-272)
  • C99标准(ISO / IEC 9899:1999):
    • 6.7.5.3/9函数声明符(包括原型)(p:119)
    • 7.15变量参数<stdarg.h>(p:249-252)
  • C89 / C90标准(ISO / IEC 9899:1990):
    • 3.5.4.3/5函数声明符(包括原型)
    • 4.8变量<stdarg.h>

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com