In C/C++, functions can be written to take variable no. of arguments. Examples are printf, sprintf, snprintf etc. The prototype of printf functions looks like int printf(const char *format, …). These functions internally use macros such as va_start, va_arg, va_end etc to get the passed parameters. But, I have observed that for every function like printf, there is another similarly defined function which takes va_list instead of … . For example, vprintf is similar to printf and has int vprintf(const char *format, va_list ap) prototype. In the same way, vsprintf and vsnprintf are also defined. Till now, I did not know the reason and used to think of it as an unnecessary wrapper.
For example, if a wrapper called myprintf needs to be written over printf
int myprintf(const char* format, …){
va_list ap;
va_start(ap,format);
???????
va_end(ap);
}
In the above code, I can not put ‘printf’ in place of ??????. Because printf is expecting variable arguments (like i, j , l) and not va_list dataype. So, in place of ??????, I should call vprintf which takes va_list.
So, I observed that it is a good practice to write 2 functions in case of variable number of arguments. One which takes variable no. of arguments as … and the other one taking va_list. An example is given below.
void vfunction (char * format, va_list ap){
/*This function does the actual work*/
}
void function(char* format, …){
/*This function just redirects to vfunction which does the work */
va_list ap;
va_start(ap,format);
vfunction(format, ap);
va_end(ap);
}
aji said,
June 14, 2008 at 6:01 pm
Quickly (my english is painfull)
“Till now, I did not know the reason and used to think of it as an unnecessary wrapper.”
is not, why ?
In most of case (ex. libraries) a function with ‘…’ *is* a wrapper of a va_list,
we can’t give a ‘…’ to an another function as is.
Ex. void func (int foo, ….) { func2 (foo + 1, …. /* err! */); }
So, now for my personal use I need any operation with a *printf, I do:
int my_printf(const char *format, ….) {
va_list args;
int ret;
va_start(args, format);
/* any op. */
ret = vprintf(format, args);
va_end(args);
return ret;
}
voilĂ .
aji said,
June 14, 2008 at 6:11 pm
I’m sorry, i will drink my coffee now, i will read your post…
An will see that i wrote what you wrote :/
JAI said,
October 17, 2011 at 3:48 pm
i am not replying i jst want to know how to implement those
va_list, va_arg, va_start, va_end if we want to create a function prototype which takes variable no of arguments such sa printf
prototype of printf();
int printf(const char*,…);