【问题标题】:How to define a c macro with multiple statement如何用多条语句定义一个c宏
【发布时间】:2018-10-27 20:38:42
【问题描述】:

我正在尝试定义一个有两个行/语句的宏,就像:

#define FLUSH_PRINTF(x) printf(x);fflush(stdout);

但由于 C 宏不能与 ';' 一起使用的限制,它不能工作。

有什么合理的解决方法吗?

PS:我知道上面的例子很奇怪,我应该使用类似普通函数的东西。但这只是一个简单的例子,我想问一下如何定义一个多重语句宏

【问题讨论】:

  • but it can't works due to the limit that C Macro can not work with ';'. 什么意思?为什么不写一个函数呢?
  • 如果您确实想这样做:#define FLUSH_PRINTF(x) {printf(x); fflush(stdout);}
  • 不应该避免 fflush 吗?
  • @KamiKaze:fflush 非常适合输出流——一般来说,它是输入流的 UB(尽管在某些平台上受支持)。

标签: c linux unix macros c-preprocessor


【解决方案1】:

这是使用do { ... } while (0) 成语的合适时机。 这也是使用variadic macro arguments的合适时机。

#define FLUSH_PRINTF(...) \
    do { \
        printf(__VA_ARGS__); \
        fflush(stdout); \
    } while (0)

您也可以使用包装函数来执行此操作,但由于使用 vprintf 涉及额外的样板文件,因此需要更多的输入。

 #include <stdarg.h>
 #include <stdio.h>

 /* optional: */ static inline 
 void
 flush_printf(const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
     vprintf(fmt, ap);
     va_end(ap);
     fflush(stdout);
 }

【讨论】:

  • 为什么是内联函数?正常的功能也可以。
  • 不错!这就是我想要的;-)
  • @MichaelWalz 我知道上面的例子很奇怪,我应该使用类似普通函数的东西。但这只是一个简单的例子,我想问一下如何定义多语句宏。
  • @MichaelWalz 我想它不需要内联,不。
【解决方案2】:

最好的解决方案是编写一个函数。我不明白你为什么首先需要一个宏。

至于如何用宏来做,简单地把它包裹在{}中:

#define FLUSH_PRINTF(x) { printf(x);fflush(stdout); }

根据 C11 6.8,这完全没问题,导致 复合语句

statement:
  labeled-statement
  compound-statement
  expression-statement
  selection-statement

如果您希望允许不带大括号的危险样式 if 语句(坏主意),例如:

if(x)
  FLUSH_PRINTF(x);
else
  FLUSH_PRINTF(y);

那么你必须使用do while(0) 技巧来包装宏:

#define FLUSH_PRINTF(x) do { printf(x);fflush(stdout); } while(0)

【讨论】:

  • 您必须使用do { ... } while (0) 进行此操作,即使您当地的风格指南绝对禁止使用您所谓的“危险风格 if 语句”。不仅如此。
  • 我不是反对者,但它不适用于多个参数。例如,FLUSH_PRINTF("hello %s\n", "Lundin");
  • 另外,天哪,在你对没有对否决票的解释大惊小怪之前,请给人们至少几分钟的时间来完成打字。 (我个人认为,一开始没有人有权对否决票做出解释,但在这种情况下,你将得到一个。)
  • (更具体地说,您需要do { } while (0) 的最重要原因是{ } ; 是一个语法错误。)
  • @zwol 不,避免 do-while(0) 意味着您会遇到危险代码的编译器错误。这就是为什么 MISRA-C:2004 中使用 do-while(0) 的建议在 MISRA-C:2012 中被删除的原因。
【解决方案3】:

在宏中使用多重表达式

#define FLUSH_PRINTF(x) (printf(x), fflush(stdout))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多