va_list可变参数的秘密

我们知道在
c++里面,如果无法确认传入的参数个数以及类型的时候,那么可以使用
省略号来指定参数列表
比如
void fun1(int a, ...)
void fun2(...)
其中比较典型的就是printf函数
printf (const char *__restrict __fmt, …)
调用
printf(“ssss %d”,10)
那么其函数内部实现的是如何的
值得注意的是
- \1. 变参处的定义或声明, 用 … 代替参数类型.
- \2. 变参 … 只能放在参数列表最末尾.
内部实现原理
其实其内部的机制就是val_list
val_list在stdarg.h头文件
type va_arg(
va_list arg_ptr,
type
);
void va_end(
va_list arg_ptr
);
void va_start(
va_list arg_ptr,
prev_param
);
其中type是指定回去参数的类型. arg_ptr是指向参数列表的指针. pre_param是指向最后一个显示声明的参数,用来回去第一个变长参数的位置
使用步骤
a)定义一个va_list类型的变量,变量是指向参数的指针。
b)va_start初始化刚定义的变量,第二个参数是最后一个显式声明的参数(也就是...之前的参数)。
c)va_arg返回变长参数的值,第二个参数是该变长参数的类型。
d)va_end将a)定义的变量重置为NULL。
具体的含义是
val_list定义一个变量列表的指针类型
va_start是将va_list对象绑定到有n个变量的传入参数列表上
va_arg是从参数列表中逐个去除数据,取出数据的类型有type决定,返回type类型的值.并且使得agv_ptr指向参数列表中的下一个参数.
当函数结束的时候调用va_end来清除va_list指向的空间,不然会发生内存泄露
所以必须知道传入参数的个数不然va_start无法绑定
例子
#include <stdarg.h>
#include <stdio.h>
void myprint(const char* format, ...) {
va_list va;
va_start(va, format);
char ch;
while (ch = *format++) {
if (ch == '%') {
ch = *format++;
if (ch == 's') {
char* ss = va_arg(va, char*);
while (*ss) {
putchar(*ss++);
}
} else if (ch == 'd') {
putchar(va_arg(va, int) + '0');
}
} else {
putchar(ch);
}
}
va_end(va);
}
int main() { myprint("hello world %s years %d\n", "!!!", 9); }
本文详细介绍了C++中的可变参数模板(va_list)及其内部实现原理,包括va_start、va_arg和va_end的使用步骤。通过一个自定义的printf函数例子展示了如何处理可变参数列表,强调了正确使用va_list避免内存泄漏的重要性。
2204

被折叠的 条评论
为什么被折叠?



