Posts Tagged variadic

Using Variadic Functions in C

I don’t really need to write on how to use va_list, va_start, va_end, va_arg because other tutorials or references do a good job of explaining it already… however, here are some notes for wrapping Varadic functions.

Firstly, note the difference between:

void myFc( int arg1, ... )

and the va_list version:

void vmyFc( int arg1, va_list args)

gnu stdc libraries (printf, etc) wrap the va_list versions (vprintf, etc) with Variadic versions (printf, etc) with the following pattern:

int vfunc(int arg1, va_list vargs){
   // do real work
}
int func(int arg1, ...){
   int retval;
   va_list vargs;
   va_start(vargs, arg1);
   retval = vfunc(arg1, vargs); 
   va_end(vargs);
   return retval;
}

When wrapping va_list functions, it is important to consider that va_list is consumed and so in the case where you will be using your va_list for multiple functions, you’ll need to save the original pointer.

GNU C doc for stdarg.h — Note the __va_copy macro.

For example, wrapping the snprintf function:

//to find the length of the string, you pass null and length 0 to the function:
len = vsnprintf(NULL, 0, fmt, vargs);

//do the allocation
str = (char*) malloc(len+1);

//and finally read the string:
vsnprintf(str, len+1, fmt, vargs);

note that we use the va_list version of snprintf (vsnprintf).

the 2nd snprintf may (depending on stdarg implementation) cause a segmentation fault. The correct/safe way of doing it would be to copy vargs and use the copy in each snprintf operation:

#ifdef __va_copy
   __va_copy(save,vargs);
#else
   save = vargs;
#endif
len = vsnpritnf(NULL, 0, fmt, save);

str = (char*) malloc(len+1);

#ifdef __va_copy
   __va_copy(save,vargs);
#else
   save = vargs;
#endif
vsnpritnf(str, len+1, fmt, save);

But as my awesome co-worker Geoff asserts, its always better to keep it simple and perhaps there’s a way to accomplish what you’re trying to do without Variadic functions. Check out my other post.

PST~ this was just a brain dump of what was on my mind as I was coding today… if you find this useful and/or find some info lacking OR just incorrect, leave a comment so I can fix it.

, , , , , , , , , , , , , , , , , , , , ,

1 Comment

Fun with Variadic functions

If you’re looking for info on implementing Variadic functions, its not here, but you can find it here (in C) or on wikipedia.

Today @ work, I wrote this awesome library to wrap fprintf, printf, etc and check that line lengths do not exceed 80 chars per line (if length exceeds 80, output warning message to stderr). The first problem I ran into was how to handle the variable number of arguments that can trail in a printf function. stdarg.h comes to the rescue with Variadic functions! Then I ran in to some problems with using the va_list more than once (since the arguments get “consumed” as the va_list pointer gets incremented as each argument is accessed). So this is resolved by copying the va_list pointer using a gnu extension, but my code has to be compiler independent, so an ifdef gets added.. blah blah blah. Because of how complex this solution is getting… I consider using snprintf and then printf the output of that (so i can get the length of the string from snprintf)… but this means I’d have to go through this 3-step process each time something is output (which is bad both because its a pain in the ass and for maintainability).. and so I’d want to wrap this with a macro. But with the variable number of arguments… there wouldn’t be an easy way of doing that either. I finally get my original idea with the Variadic function working… and then I realize, that each output generated by printf is not always one line, I can printf multiple lines… or use multiple printfs to generate one line. AHH.. so, introduce a static int that counts chars per line… OR… all this is being dumped to a file anyway… the simplest solution… JUST READ THE FILE at the very end and check line length!

The lesson here, keep it simple 😛 Though my Varidic solution is far more elegant IMO… though excessive for what I was trying to accomplish.

, , ,

1 Comment