#define and functions with variable length arguments

I have zillions of my_printf () function calls in a huge program. Now I want to convert them all so that the function accepts a new integer argument (name it x) without changing the number of calls. If my_printf used only one string argument, I could do something like this:

#define my_printf(str) _my_printf(x,str) void _my_printf(int x,char *str) // changed from my_printf(char *str) { // stuff } 

But since my_printf takes a variable number of arguments, I'm not sure how to do this. It can be done?

EDIT: for those who are wondering why I should do such a thing, here is an example:

 #if BELT_AND_BRACES_DIAGNOSTIC_MODE #define function(x) _function(__FILE__,__LINE__,x) #else // speed critical optimised mode #define function(x) _function(x) #endif #if BELT_AND_BRACES_DIAGNOSTIC_MODE void _function(char *file,int line,int x) #else void _function(int x) #endif { // stuff #if BELT_AND_BRACES_DIAGNOSTIC_MODE if (something_went_wrong) { printf("Cock up in function when called from %s line %d\n",file,line); } #endif } 
+6
c
source share
6 answers

You can use C99 variable macros:

 #define my_printf(...) my_printf_(x, __VA_ARGS__) 

As the Microsoft implementation suppresses commas, the str argument can be added explicitly

 #define my_printf(str, ...) my_printf_(x, str, __VA_ARGS__) 

but this will result in a syntax error in the C standard when called without variational arguments

 my_printf("foo") 

or an empty argument list

 my_printf("foo",) 

So I would go with the first version.

+7
source share

If the code can be compiled as C99 code, you can define a variable macro

 #define my_printf(str, args...) _my_printf(x, str, ##__VA_ARGS__) 

The preprocessor will replace the arguments ... and the GNU preprocessor will remove the trailing comma if the macro is called only with the str argument.

+8
source share

It’s best, of course, to bite a bullet and edit the code. Otherwise, you create a “secret” that must be solved by all future code developers. Even if it's just you, this is the smart trick that you forget about. It sucks to return, and to be perplexed by strange senseless seeming macros.

However, if you use the GNU toolchain, you can study the varargs macros .

+7
source share

Not with standard C89 macros, you cannot. However, you can get the same effect with functions by snatching the bulk of your my_printf function into a vmy_printf function similar to the vprintf standard:

 #include <stdarg.h> int vmy_printf(int x, const char *format, va_list ap) { /* main body of my_printf goes here, taking its varargs from ap */ } /* new_my_printf(), for callers who know about the x parameter */ int new_my_printf(int x, const char *format, ...) { int n; va_list ap; va_start(ap, format); n = vmy_printf(x, format, ap); va_end(ap); return n; } /* my_printf(), for the old callers who don't know about x */ int my_printf(const char *format, ...) { int n; va_list ap; va_start(ap, format); n = vmy_printf(DEFAULT_X, format, ap); va_end(ap); return n; } 

(That's why such versions of v ... all the standard varargs functions exist.)

+2
source share

If my_printf already accepts a variable number of arguments, I'm not sure why you need to wrap "another argument" in a macro ... Just insert new calls with an additional argument and do with it; old calls should work as expected.

0
source share

A simple solution to this problem is ...

 #define my_printf(x) printf x 

(note missing curly braces)

To call it, use:

 my_printf((any number of arguments)) 

(note the double curly braces)

0
source share

All Articles