想知道一些#define技巧

时间:2010-04-25 04:27:32

标签: c c-preprocessor

在阅读我的小组项目的代码时,我遇到了许多DEFINE,其中一些似乎很奇怪。要概括它,请查看以下2个示例。

示例1:

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

“##”在这种情况下意味着什么?我试图删除它们,并编写代码如“char buf [1024]; SNPRINTF(buf,”%s,%s“,”abcd“,”efg“);”这产生了相同的结果。所以“##”似乎毫无用处,也没有伤害我。

示例2:

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

有必要将内部代码填充到do{}while(0)语句中吗?什么用途?

2 个答案:

答案 0 :(得分:8)

...根据C99标准识别variadic macro。根据标准,表示右侧“所有剩余参数”扩展的标记是__VA_ARGS__ - 我想你正在使用一些带有非标准扩展的C编译器,允许不同的形式你'使用(##是预处理程序令牌粘贴操作符,但我不知道这在哪里适用)。

第二种形式是一种经典技巧(甚至比C89更老),以确保宏在行为正确后为;,在else未绑定到错误的if之后, 等等。基本上,将do ... while中所需的多个和条件语句安全地“嵌套”在一个后面需要分号的块中,在语法上“就好像”宏调用是一个功能调用。

答案 1 :(得分:3)

两个人按顺序回答你的问题:

  1. 是粘贴操作符,因此它并没有真正做任何事情。我认为(找不到任何引用)有非标准版本的它会吃掉前面的逗号,如果它是空的,那么也许这就是它的用途。

  2. 正如已经提到的,do{...}while(0)是一个标准技巧,可以确保粘贴到...中的任何内容都可以作为单个语句处理。它通常可以让你写出:
  3. if( floon )
      CLOSE(floon);
    

    不用担心。