【问题标题】:Wonder about some #define tricks想知道一些#define 技巧
【发布时间】:2010-04-25 04:27:32
【问题描述】:

在阅读我的小组项目的代码时,我遇到了很多 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) 语句中吗?什么用途?

【问题讨论】:

标签: c c-preprocessor


【解决方案1】:

... 根据 C99 标准标识 variadic macro。根据标准,表示右侧“所有剩余参数”扩展的标记是__VA_ARGS__——我想你正在使用一些带有非标准扩展的 C 编译器,它允许你使用不同的形式使用(## 是预处理器标记粘贴操作符,但我不明白它是如何应用在这里的)。

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

【讨论】:

【解决方案2】:

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

  1. 是粘贴运算符,因此它并没有真正在那里做任何事情。我认为(找不到任何参考资料)它的非标准版本会在前面的逗号为空时吃掉它,所以也许这就是它的用途。

    李>
  2. 如前所述,do{...}while(0) 是一个标准技巧,可确保粘贴到 ... 中的任何内容都可以视为单个语句。它通常允许您编写如下内容:
if( floon )
  CLOSE(floon);

不用担心。

【讨论】:

    猜你喜欢
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多