【问题标题】:function like macro curly braces or do..while [duplicate]像宏大括号或do..while [重复]
【发布时间】:2012-11-25 10:42:48
【问题描述】:

可能重复:
Do-While and if-else statements in C/C++ macros

gcc (GCC) 4.7.2
c89

你好,

我有以下类似函数的宏,只是想知道跨多行使用时的首选用法是什么。最好使用花括号或 do..while(0) 循环。

通常我对所有事情都使用 do..while(0)。但是我看到一些项目只使用花括号,我不确定哪个更好。

做..同时

#define DSO_ERROR(msg, res_handle_module, mem_pool, size)   do {        \
        char *dso_error = apr_palloc((apr_pool_t*)mem_pool, size);      \
        apr_dso_error((apr_dso_handle_t*)res_handle_module, (char*)dso_error, (apr_size_t)size); \
        LOG_ERR("%s dso error %s", (char*)msg, dso_error);              \
        goto dso_failure;                                               \
    } while(0); 

花括号

#define DSO_ERROR(msg, res_handle_module, mem_pool, size) {             \
        char *dso_error = apr_palloc((apr_pool_t*)mem_pool, size);      \
        apr_dso_error((apr_dso_handle_t*)res_handle_module, (char*)dso_error, (apr_size_t)size); \
        LOG_ERR("%s dso error %s", (char*)msg, dso_error);              \
        goto dso_failure;                                               \
    }

唯一的区别是分号将被预设在 do..while 循环而不是花括号上。

非常感谢您的任何建议,

【问题讨论】:

  • 天哪,这是丑陋的代码。 (无意冒犯,我只是很惊讶)。
  • do { ... } while (0) 的末尾添加分号首先破坏了使用do { ... } while (0) 的目的。仅大括号版本的缺点是不能编写if (something) DSO_ERROR(...); else { ... },因为分号是if 之后的空语句,而else 是语法错误。使用 do { ... } while (0) 的更正版本,if / else 符号的工作方式与您所期望的一样,如果宏实际上是一个函数。

标签: c macros


【解决方案1】:

通常您没有在宏中的do { ... } while (0) 上有分号。

您为宏设置do { ... } while (0) 的原因是,您可以在源代码中使用宏并添加分号,而不会出现额外的空语句。我猜这主要是出于历史原因,因为在许多情况下,有空语句(即只有分号而没有任何语句)并没有任何作用。

【讨论】:

  • "...什么也不做" 除了悬空 else-problem
【解决方案2】:

这段代码会有问题:

if (one) 
  DSO_ERROR("one", ...);
else
  DSO_ERROR("two", ...);

因此,如果您使用不带分号的 do-while-Macro,就可以了。

【讨论】:

    【解决方案3】:

    花括号版本会像这样中断用法:

    if( foo )
      DSO_ERROR("Foo occured!", my_module, the_pool, 4711);
    else
      printf("All is well, there is no foo\n");
    

    这正是do ... while(0) 构造的原因。所以这似乎值得避免。

    【讨论】:

    • 正如 OP 所写,do...while(0) 版本也会中断,因为它末尾有一个额外的分号。编写 do...while(0) 的正确方法是不使用分号。
    猜你喜欢
    • 2012-05-30
    • 2010-11-07
    • 2011-07-27
    • 2016-04-20
    • 2013-10-07
    • 2021-04-14
    • 2011-01-08
    • 1970-01-01
    相关资源
    最近更新 更多