views:

127

answers:

2

Whlie reading codes of my group project, I come across many DEFINEs, and some of them seems strange. To generalize it, please look at the following 2 examples.

Example 1:

#define SNPRINTF(dst, fmt, arg...)  snprintf(dst, sizeof(dst), fmt, ##arg)

what does "##" means in this circumstance? I've tried to delete both of them, and write codes like "char buf[1024]; SNPRINTF(buf,"%s,%s","abcd","efg");" which produced the same result. So "##" seems no use and no harm to me.

Example 2:

#define CLOSE(fd)   do  {   \
        if (-1 != (fd)) {   \
                    close(fd);  \
                    (fd)    = -1;   \
                }   \
} while (0)

Necessary to stuff the inner code to the do{}while(0) statement? what's the use?

Thanks!

+8  A: 

The ... identify a variadic macro per the C99 standard. The token to indicate expansion of "all remaining argument" in the right hand side, per the standard, is __VA_ARGS__ -- I imagine you're using some C compiler with a non-standard extension that allows the different forms you're using (## is the preprocessor token-pasting operator, but I don't see how that applies here).

The second form is a classic trick (older even than C89) to ensure a ; after the macro behaves correctly, an else after it doesn't bind to the wrong if, and so on. Basically, wrapping the multiple and conditional statements needed in that do...while safely "nests" them inside a block that requires a semicolon afterwards, syntactically "just as if" the macro invocation was instead a function call.

Alex Martelli
the `args...` and `##args` combination is a GCC preprocessor extension, see http://gcc.gnu.org/onlinedocs/gcc-4.4.3/cpp/Variadic-Macros.html
Hasturkun
+3  A: 

Two answer your questions in order:

  1. ## is the pasting operator, and so its not really doing anything there. I think (couldn't find any references) that there are non-standard versions of it that will eat a preceding comma if its empty, so maybe that's what this is for.
  2. As already mentioned, the do{...}while(0) thing is a standard trick to ensure that whatever gets pasted into the ... can be treated as a single statement. It generally lets you write things like:
if( floon )
  CLOSE(floon);

without worrying about it.

swestrup