Tag Archives: macro

Variadic C functions

You can’t do variadic C functions. Everyone knows that. That’s the realm of C++, or even PHP, but not C.

Except you can.

I needed to do this last week. When I say needed, I didn’t NEED to, but my sense of neatness rebelled when for the hundredth time I had to create functionname(parameter,parameter) and functionname_default(parameter) which just called functionname(parameter,0);

How you do it is with the preprocessor, obviously. There’s no real other way it could be done. Here’s an example of how.

#include <stdio.h>

#define DO_TEST_1(x) do_test(x,1)
#define DO_TEST_2(x,y) do_test(x,y)

#define TEST_MACRO(_1,_2,FUNC,...) FUNC
#define DO_TEST(...) TEST_MACRO(__VA_ARGS__,DO_TEST_2,DO_TEST_1)(__VA_ARGS__)

void do_test(const char *name,double val)
{
    printf("%s %f\n",name,val);
}

int main(int argc,char **argv)
{
    DO_TEST("test");
    DO_TEST("test",2.3);
    return 0;
}

Three levels of macros. Yeah it’s pretty awful, which may explain why I liked it so much. But how does it work? Let’s break it down by following each step for each called function.

The initial called function DO_TEST(“test”); DO_TEST(“test,2.3);
Apply DO_TEST(…) TEST_MACRO(“test”,DO_TEST_2,DO_TEST_1)(“test”); TEST_MACRO(“test”,2.3,DO_TEST_2,DO_TEST_1)(“test”,2.3);
explanatory step TEST_MACRO(“test”=_1,DO_TEST_2=_2,DO_TEST_1=FUNC,…=empty)(“test”); TEST_MACRO(“test”=_1,2.3=_2,DO_TEST_2=FUNC,…=DO_TEST_1)(“test”,2.3);
Apply TEST_MACRO(_1,_2,FUNC,…) DO_TEST_1(“test”); DO_TEST_2(“test”,2.3);
And finally do_test(“test”,1); do_test(“test”,2.3);

Obviously the explanatory step never actually happens, but it allows you to see how the __VA_ARGS__ in DO_TEST will push along the values of the actual macro which is called, allowing you to end up with a different macro for different number of parameters, which then should be all you need.

This example only works for one and two parameters, it can be made to work with as many as you like. For example, this for up to four

#define TEST_MACRO(_1,_2,_3,_4,FUNC,...) FUNC
#define DO_TEST(...) TEST_MACRO(__VA_ARGS__,DO_TEST_4,DO_TEST_3,DO_TEST_2,DO_TEST_1)(__VA_ARGS__)

The only limit to the number of parameters here is zero. That’s possible, but the example becomes a bit more complicated and I don’t think it’s really necessary for this post. If you need that, you’ll need to use ##__VA_ARGS__ as part of the solution.

Logging with a bit more brain

I expect many of you will use the preprocessor macros of __LINE__ and __FILE__ for logging. It’s fairly standard practice, but if you don’t, then I’ll introduce you to it.

#define LOG(x...) log(__FILE__,__LINE__,x)

This will allow you to do, for example

LOG("Something went wrong\n");

and it will include the file and the line number in the log function as the first two parameters.

That’s fairly common. Now, what’s less common is a thing I worked out for more complex logging.
I needed to log a message which may appear very regularly, but I didn’t want to spam logfiles with millions of them, I only needed to see the first one. I thought that I’ll have to tag the log with some kind of hash value for checking when it was last used, or something like that, when I had a brainstorm. It could all be done in the preprocessor.

#define LOGO(x...) { static int loginst__LINE__=0; if (loginst__LINE__==0){ loginst__LINE__=1; log(__FILE__,__LINE__,x);}}

As you can see, the variable loginst_nnn will only be used once per file, so is unique (unless you use LOGO twice on one line, don’t do that. The macro definition has to be all on one line, obviously. I mention this because wordpress is likely to wrap it unless your screen is very wide.

That got me thinking, what else can I do with the preprocessor like this. And I came up with:

#define LOGN(n,x...) { static int loginst__LINE__=0; if (loginst__LINE__++==0){ log(__FILE__,__LINE__,x);} if (loginst__LINE__==w) loginst__LINE__=0;}

This one logs every nth occurence of the log message. I also came up with

#define LOGT(t,x...) { static time_t loginst__LINE__=0; if (loginst__LINE__<=time(NULL)){ log(__FILE__,__LINE__,x);loginst__LINE__=time(NULL)+t;}}

which only logs at most once every t seconds.

All in all, I was quite pleased with that. They’re simple, effective, and a LOT more efficient than some other solutions I’ve seen out there.

 

Variable length C macros

This article was originally published on the LGP Blog on Saturday, May 30th, 2009

Something that came up in porting X2 and X3 is that Visual Studio in Windows handles variable length macros, and as far as we could see, GCC didnt.

This means that in gcc, if you wanted to create a define that would do a job and report where it was called from, you would need to do something like:

void mydebug(const char *file,int line,const char *fmt,...)

#define DEBUGOUT1(x) mydebug(__FILE__,__LINE__,x)
#define DEBUGOUT2(x,y) mydebug(__FILE__,__LINE__,x,y)
#define DEBUGOUT3(x,y,z) mydebug(__FILE__,__LINE__,x,y,z)

and so on…

However, there is a solution which does the job, which we found after a fair amount of investigation. The recommended method would be

#define DEBUGOUT(x,y...) mydebug(__FILE__,__LINE__,x,y)

Which will work, but only if you actually add a second parameter to the DEBUGOUT call. Without, it will expand

DEBUGOUT(x)

to

mydebug(__FILE__,__LINE__,x,)

which will obviously fail to compile. To fix this, simply bear in mind that … in the macro just means everything else, so you can do

#define DEBUGOUT(x...) mydebug(__FILE__,__LINE__,x)

which then works with single and multiple values in macros, x becomes the fmt AND the … for the mydebug .