Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C/C++ va_arg - Is there a way to skip an argument?

I am wanting to add functionality to sprintf(). Specifically, I want to be able to pass my own POD data types to it, but I am unsure of how to do this.

Supposedly, if you create the va_list, you can pass it off to vsprintf() and have it do the hard work for you - but I still need to access the va_list, and extract items myself before passing the va_list to vsprintf().

For example, assume the following code:

struct mypod {
    int somedata;
}; // just for example, you know

// somewhere else in the code...
mypod mp;
mp.somedata = 5325;
my_sprintf(myChrPtr, "%z", mp);

With the new %z code corresponding to my new data type.

I understand only pointers and POD structures can be passed, that's no big deal. I am wondering, though, that what happens if I get to the end of the va_list (by getting the args using va_arg()) and then pass it to vsprintf()?

Thank you!

like image 745
FurryHead Avatar asked Nov 05 '22 22:11

FurryHead


1 Answers

Given that va_arg must be called in the right order and with the right type for proper behavior I think you have to consume the fmt piecemeal while processing the parts you care about and passing the rest to vsprintf:

void
mysprintf(char *dst, char *fmt, ...)
{
    char *p = fmt;
    va_list va;

    va_start(va, fmt);
    do {
        char *q = strchr(p, '|');
        if (q) {
            /* really should take const char *fmt and not write on it like this... */
            *q++ = '\0';
        }
        dst += vsprintf(dst, p, va);  /* let vsprintf do a subset */
        if (q) {
            dst += sprintf(dst, "%d", va_arg(va, int));  /* consume 1 int */
        }
        p = q;
    } while (p);

    va_end(va);
}


strcpy(fmt, "%s|%s|%s");  /* mutable fmt */
mysprintf(buf, fmt, "hello", 7, "world", 8, "!");

In my example I just took | to be like %d but a real example with additional %... escapes will be much more complex.

like image 181
Ben Jackson Avatar answered Nov 13 '22 02:11

Ben Jackson