1

While 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?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
kingkai
  • 3,669
  • 3
  • 19
  • 13
  • The do...while question has been answered before. I'll try to dig up a link. – dmckee --- ex-moderator kitten Apr 25 '10 at 04:31
  • 1
    Found just the ## part of the question: http://stackoverflow.com/questions/2025858/what-does-mean-for-the-c-preprocessor – dmckee --- ex-moderator kitten Apr 25 '10 at 04:33
  • 1
    This answer: http://stackoverflow.com/questions/1829930/multi-statement-macros-in-c/1830046#1830046 discusses the `do while` matter, but I know there is question separate question out there. Here they are: http://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we-define-a-macro http://stackoverflow.com/questions/154136/why-are-there-sometimes-meaningless-do-while-and-if-else-statements-in-c-c-macr http://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for http://stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block-closed maybe others – dmckee --- ex-moderator kitten Apr 25 '10 at 04:37
  • @dmckee thanks for the valuable link! How do you "dig up"? Just by memory, or the site provides us some useful tools besides tags? – kingkai Apr 25 '10 at 04:45
  • The search has some operators described here http://stackoverflow.com/search but mostly I dug through pages of search results. That's easier to stomach when you *know* the answer is there. – dmckee --- ex-moderator kitten Apr 25 '10 at 05:07

2 Answers2

8

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
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 1
    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 Apr 25 '10 at 08:43
3

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
  • 4,079
  • 3
  • 22
  • 33