可变参数
来自 cppreference.com
可变函数是可以使用不同数量参数调用的函数。
只有原型化函数声明可以是可变的。这由形式为...的参数表示,该参数必须出现在参数列表的最后并且必须紧随至少一个命名参数(直到 C23)。省略号参数和前面的参数必须用,分隔。
// Prototyped 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 printz(...); // OK since C23 and in C++ // Error until C23: ... must follow at least one named parameter // int printy(..., const char* fmt); // Error: ... must be the last // int printa(const char* fmt...); // Error in C: ',' is required; OK in C++
在函数调用中,每个作为可变参数列表一部分的参数都会进行特殊的隐式转换,称为默认参数提升。
在使用可变参数的函数主体内部,可以使用<stdarg.h>
库设施访问这些参数的值。
在头文件
<stdarg.h> 中定义 | |
启用访问可变函数参数 (函数宏) | |
访问下一个可变函数参数 (函数宏) | |
(C99) |
复制可变函数参数 (函数宏) |
结束遍历可变函数参数 (函数宏) | |
保存 va_start、va_arg、va_end 和 va_copy 所需的信息 (typedef) |
内容 |
[编辑] 注释
尽管旧式(无原型)函数声明允许后续函数调用使用任意数量的参数,但它们不允许是可变的(截至 C89)。此类函数的定义必须指定固定数量的参数,并且不能使用 stdarg.h
宏。
// old-style declaration, removed in C23 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 at least one of these calls is undefined, depending on // the number of parameters the function is defined to take
[编辑] 示例
运行此代码
#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); }
输出
[10:21:38] logging 1 2 3...
[编辑] 参考文献
- C17 标准 (ISO/IEC 9899:2018)
- 6.7.6.3/9 函数声明符(包括原型)(p: 96)
- 7.16 可变参数 <stdarg.h> (p: 197-199)
- 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>
[编辑] 另请参阅
C++ 文档 关于 可变参数
|