前言
在C/C++中,可变参函数(Variadic Function)使用省略号…接受不定数量、不定类型的参数,这类函数需要借助<stdarg.h>(C)或者<cstdarg>(C++)中的宏来解析参数。
用法
函数的声明
可变参函数的声明格式为:return_type func_name(fixed_arg,…);
- fixed_arg:至少需要一个固定参数(用于确定可变参数的起始位置)
- …:表示后续参数的数量和类型不确定
关键宏
- va_list:用于声明参数列表变量。
- va_start(va_list,fixed_arg):初始化参数列表,从fixed_arg之后开始。
- va_arg(va_list,type):逐个提取参数,需要指定类型type
- va_end(va_list):清理参数列表
实例:求和函数
#include <stdio.h>
#include <stdarg.h>
// 功能:计算不定数量整数的和
int sum(int count, ...) {
int total = 0;
va_list args; // 声明参数列表变量
va_start(args, count); // 初始化,从 count 之后开始
for (int i = 0; i < count; i++) {
int num = va_arg(args, int); // 逐个提取 int 类型参数
total += num;
}
va_end(args); // 清理
return total;
}
int main() {
printf("Sum1: %d\n", sum(3, 10, 20, 30)); // 输出 60
printf("Sum2: %d\n", sum(5, 1, 2, 3, 4, 5)); // 输出 15
return 0;
}
实例:自定义打印函数
#include <stdio.h>
#include <stdarg.h>
void my_printf(const char* format, ...) {
va_list args;
va_start(args, format);
while (*format != '\0') {
if (*format == '%') {
format++; // 跳过 '%'
switch (*format) {
case 'd': {
int num = va_arg(args, int);
printf("%d", num);
break;
}
case 'f': {
double num = va_arg(args, double);
printf("%f", num);
break;
}
case 's': {
char* str = va_arg(args, char*);
printf("%s", str);
break;
}
default:
putchar(*format);
}
} else {
putchar(*format);
}
format++;
}
va_end(args);
}
int main() {
my_printf("Name: %s, Age: %d, Score: %f\n", "Alice", 25, 95.5);
// 输出:Name: Alice, Age: 25, Score: 95.500000
return 0;
}
原理
因为函数的传参是从右向左进行传参,栈通常向低地址增长,后压入的参数位于更低的地址,因此就可以根据最后入栈的固定参数依次访问到可变参数。va_list定义为指向参数列表的指针(如char*),根据我们使用va_arg(arg,type)传入的type调整指针指向下一个参数的起始位置,依次获取参数。最后使用va_end进行资源的清理。
使用场景
一般可用于日志输出,参数比较灵活,不确定的函数之中。