6

Let's say I want to do something like this

void my_printf(char *fmt,...) { char buf[big enough]; sprintf(buf,fmt,...); } 

What is the proper way of passing the variable number of arguments directly to a function with accepts variable arguments?

2
  • How are you going to know the buffer is big enough? And you should really return the number of conversions performed by sprintf(), else users have no way of knowing the function worked. Commented Mar 10, 2010 at 22:23
  • I striped everything that wasn't essential to illustrating my point. Obviously in my release code I'm much more thorough :) Commented Mar 10, 2010 at 22:26

3 Answers 3

9

sprintf has a va_list form called vsprintf. Pass the va_list you construct locally to it as the last argument.

void my_printf(char *fmt,...) { va_list ap; va_start(ap, fmt); char buf[big enough]; vsprintf(buf,fmt,ap); va_end(ap); } 
Sign up to request clarification or add additional context in comments.

2 Comments

The operative header is <stdarg.h>.
If it's available, you should use vsnprintf.
2

I'm not sure how useful this code will be, as it is C++, but it shows how to check, using a Win32 specific function vsnprintf(), that the buffer allocated is big enough and if not allocates a bigger one. And it returns a std::string, so you would have to use malloc/realloc to handle that. But what the hell:

string Format( const char * fmt, ... ) { const int BUFSIZE = 1024; int size = BUFSIZE, rv = -1; vector <char> buf( size ); do { va_list valist; va_start(valist, fmt ); // if vsnprintf() returns < 0, the buffer wasn't big enough // so increase buffer size and try again rv = _vsnprintf( &buf[0], size, fmt, valist ); va_end( valist ); size *= 2; buf.resize( size ); } while( rv < 0 ); return string( &buf[0] ); } 

Comments

-1

You can us the vsprintf style functions to get printf style printing for your variable length parameter. However there is no requrement to do so. You can if you choose write your function to keep accepting parameters until it encounters a null pointer.

 va_list ap; char *param; va_start(ap,fmt); param = va_arg(ap,char*); while(param) { do something... param = va_arg(ap,char*); } 

or you can have the number of parameters as the first param to your function

void my_printf(int param_num,...) { va_list ap; char *param; va_start(ap,fmt); while(param_num) { do something... param = va_arg(ap,char*); param_num--; } } 

Its really up to you, the possibilities are limitless. I think the only real requirement to the ellipses is that it has at least one parameter before the ellipses.

2 Comments

requiring the user to specify the number of parameters would be a design catastrophe
my point is the ... is not pigeon holed into a certain usage. The user of the function can decide what is best for their situation. Passing in the number of parameters is no different than having the number embeded in a string... ie sprintf("%d %d",a,b) is just the same as yourprintf(2,a,b), sprintf is just as prone to user error.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.