Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

#define and functions with variable length arguments

Tags:

c

I have zillions of my_printf() function calls in a huge program. I now want to convert them all so that the function takes a new integer argument (call it x) without having to edit the zillions of calls. If my_printf only ever took exactly one string argument then 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 as my_printf takes a variable number of arguments I'm not sure how to do it. Can it be done?

EDIT: for those wondering why I should want to do such a thing, here's a related 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
}
like image 658
Mick Avatar asked Sep 29 '09 10:09

Mick


3 Answers

You may use C99 variadic macros:

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

As Microsoft's implementation suppresse trailing commas, the str argument can be added explicitly

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

but this would lead to a syntax error in standard C when invoked without variadic arguments

my_printf("foo")

or an empty argument list

my_printf("foo",)

Therefore, I'd go with the first version.

like image 116
Christoph Avatar answered Sep 20 '22 23:09

Christoph


If the code can be compiled as C99 code, you can define a variadic 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 in case the macro is invoked only with the str argument.

like image 42
philant Avatar answered Sep 20 '22 23:09

philant


The best thing is of course to bite the bullet and edit the code. Otherwise you're creating a "mystery", that needs to be solved by all future maintainers of the code. Even if that's only you, this is exactly the kind of clever trick that you will forget all about. It sucks to come back, and be puzzled by strange pointless-seeming macros.

That said, if you're using a GNU toolchain, you can perhaps look into using varargs macros.

like image 27
unwind Avatar answered Sep 24 '22 23:09

unwind