带有 if 语句的 C 预处理器

问题描述 投票:0回答:4

我有以下宏:

#define IF_TRACE_ENABLED(level)  if (IsTraceEnabled(level))

用户代码应如下所示:

IF_TRACE_ENABLED(LEVEL1)
{
    ... some very smart code
}

这里强调的是大括号 - 我想防止宏中的“if”“吃掉”其他代码:

if (...)
   IF_TRACE_ENABLED(LEVEL1)
      printf(....);
else
   bla bla bla

在此示例中

IF_TRACE_ENABLED
“吃掉”else 块。

有没有办法强制用户代码在没有大写刹车的情况下不编译,或者有其他定义宏来实现安全?

macros c-preprocessor
4个回答
11
投票

这不会强制宏的用户使用大括号,但会防止

else
子句被无意中吃掉:

#define IF_TRACE_ENABLED(level)  if (!IsTraceEnabled(level)) {} else 

旁注:问题的第二个示例中

printf()
周围的大括号不会解决问题 - 与
else
关联的
bla bla bla
仍将绑定到宏中的
if
语句。


2
投票

你可以试试这个:

#define IF_TRACE_ENABLED(level) do { if(IsTraceEnabled(level)) {
#define END_TRACE_ENABLED } } while(0);

我认为没有任何方法可以仅从宏的开头行“强制”良好的语法。您需要使用两个。

编辑

我在宏内添加了一对额外的大括号以避免所有歧义。

响应评论,这个宏应该这样使用:

IF_TRACE_ENABLED(LEVEL1)
    printf("Trace\n");
END_TRACE_ENABLED

不作为声明。根据记录,我认为这是对预处理器的滥用,任何人都不应该这样做。直接写出来有什么问题吗?如果需要的话,用

#ifdef DEBUG
括起来。


0
投票

这应该可行,但是您也可以将 if 块的内容作为参数传递给宏:

#define IF_TRACE_ENABLED(level,content)  { if (IsTraceEnabled(level)) {content} }

0
投票

if (expression)

一般可以重写为

for (bool allow = true; allow && (expression); allow = false)

这消除了对其他悬空的任何担忧。它不强制使用大括号,但可以说,由于 C 和 C++ 不强制使用大括号,因此您也不应该使用大括号。

应该提到的是,您正在更改宏的客户端代码中的

break
continue
行为,但这对我来说在现实世界的使用中从来都不是真正的问题。像这样预测指标/日志记录代码执行的宏通常不会与本地流量控制交互。

© www.soinside.com 2019 - 2024. All rights reserved.