无法理解是否在#define中

时间:2014-04-04 11:13:47

标签: c++ c

任何人都可以帮我理解这条线的含义吗?

我知道它是一种宏结构,但是在代码中提出了什么呢?

#define ReturnErr(fCall) if (iErr = (fCall), (iErr != NO_ERRORS)) {return iErr;}

5 个答案:

答案 0 :(得分:5)

合格的猜测是宏应该像这样使用:

err_t func (void)
{
  err_t iErr;

  ReturnErr(some_function());
  ...

  return NO_ERRORS;
}

在这种情况下,宏扩展为:

err_t func (void)
{
  err_t iErr;

  if(iErr = some_function(), iErr != NO_ERRORS) { return iErr; }
  ...

  return NO_ERRORS;
}

反过来又是一种不必要的混淆写作方式

err_t func (void)
{
  err_t iErr;

  iErr = some_function();
  if(iErr != NO_ERRORS)
  { 
    return iErr; 
  }
  ...

  return NO_ERRORS;
}

换句话说,宏可能是一次又一次地重复相同的错误处理代码的尝试。

答案 1 :(得分:2)

宏是文本替换。这意味着,如果有人写,例如,

ReturnErr(x)

然后他们的代码将被处理为:

if ( iErr = (x), (iErr != NO_ERRORS) )
{
    return iErr;
}

这是一种糟糕的风格,但是他们可能希望在发生故障时让函数返回并节省一些打字,而不是在需要检查错误代码的每个点复制代码。

答案 2 :(得分:2)

宏采用名为fCAll的单个参数。宏扩展为以下代码:

if (iErr = (fCall), (iErr != NO_ERRORS)) {
   return iErr;
}

我猜你对if语句中,运算符的使用感到困惑。

  

在C和C ++编程语言中,逗号运算符(由...表示)   token ,)是一个二元运算符,它计算第一个操作数并丢弃   结果,然后计算第二个操作数并返回该值(和类型)。

这是wikipedia article btw。

的引用

因此,当且仅当iErr != NO_ERRORS即有错误时,才会执行正文中的陈述。

答案 3 :(得分:1)

宏想要使用值iErr两次,一次在if,一次在return,但是 它只想执行fCall一次。它使用逗号来计算其操作数,但仅与最右边的数字相等。

因此,如果我们手工扩展并进行一些重构,我们得到:

iErr = (... macro argument here ...);
if((iErr != NO_ERRORS)) {
    return iErr;
}

答案 4 :(得分:0)

Lundin和其他人已经解释了宏的作者的意图。但是,它的编写方式也会产生意想不到的后果,因为它不遵循编写多语句宏的规范方法,即:将它包装在do..while(0)循环中。

为什么呢?考虑:

if( someCondition)  ReturnErr(fCall); else doSomethingElse();

这在语法上失败了,因为程序员在扩展宏的大括号后面的分号是一个空语句,使 else 悬空。

程序员可以选择删除多余的分号,以便安抚编译器,编写

if( someCondition)  ReturnErr(fCall) else doSomethingElse();

这可能不是他/她的意图,因为 else 部分现在以静默方式附加到宏的 if 。这非常糟糕,因为它完全不可见。

规范方式是:

#define ReturnErr(fCall) do { if (iErr = (fCall), (iErr != NO_ERRORS)) \
                              return iErr; \
                            } while(0)

这允许,甚至在结尾处需要语法上自然的分号,并且只要需要一个语句就算作单个语句。

@Jens :: - )