Mike
Mike

Reputation: 60771

C, Dealing with variable argument functions

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?

Upvotes: 6

Views: 692

Answers (3)

Medran
Medran

Reputation: 443

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.

Upvotes: -1

anon
anon

Reputation:

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] );
}

Upvotes: 2

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506925

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);
}

Upvotes: 9

Related Questions