预处理器定义函数期望表达式



我试过这样定义:

#define Math.Pow(a,b) (int result=1; for (int i=0; i<b; i++) result*=a; return result;)
当我在代码中使用Math.Pow(a,b)时,我得到一个错误:

期望一个表达式。

我试图把这个定义放在另一个函数中,比如

int Power(int a, int b)
{int result=1; for (int i=0; i<b; i++) result*=a; return result;}

#define Math.Pow(a,b) (Power(a,b))

但是我得到了相同的错误

不能在宏名中使用.字符。即使可以,宏中的return语句也不会从宏本身返回值。请记住,宏只是在编译器被调用之前的文本替换,因此return将应用于调用代码,这不是您在这种情况下真正想要的。

要做你正在尝试的事情,使用模板化函数代替:

struct Math
{
    template<typename T>
    static T Power(T a, T b)
    {
        T result = 1;
        for (int i = 0; i < b; ++i)
            result *= a;
        return result;
    }
};

或:

namespace Math
{
    template<typename T>
    T Power(T a, T b)
    {
        T result = 1;
        for (int i = 0; i < b; ++i)
            result *= a;
        return result;
    }
}

无论哪种方式,你都可以这样调用它:

Math::Power(value1, value2);

除了名称中的.问题之外,您的宏引入了多个语句,这些语句用括号分组,例如(statement;声明;语句。)这不是合法的C/c++语法。但是,您可以使用逗号操作符对多个单独的表达式求值(但不能执行多个任意语句)。然而,有很多更好的方法来做你想做的事情。

讨论

使用宏时,预处理器在编译器之前运行,并将代码中的宏替换为指定的别名文本。

您的第一个问题是宏的名称包含点.。这是不允许的,因为宏的名称是一个标识符。标识符名称不允许使用点字符,因为.用于operator.(即点操作符)。所以编译器的抱怨是正确的。

假设我们通过为宏使用一个合法的名称来克服这个问题,例如Math_Pow

现在让我们假设你有以下一段代码:

#define Math_Pow(a,b) (int result=1; for (int i=0; i<b; i++) result*=a; return result;)
int main () {
  Math_Pow(1, 3);
}
现在,当你的宏将被预处理器替换为上面代码中的别名文本时,编译器的代码提要将是:

int main () {
  (int result=1; for (int i=0; i<b; i++) result*=a; return result;)
}

以上不是合法的c++,所以编译器再次报错。

现在假设我们使用大括号代替圆括号(例如,。#define Math_Pow(a,b) {int result=1; for (int i=0; i<b; i++) result*=a; return result;})

现在代码变成:

int main () {
  {int result=1; for (int i=0; i<b; i++) result*=a; return result;}
}

上面的代码在语法上是正确的,但是它有一个逻辑缺陷。如果returnmainresult。这意味着如果你在一个函数中声明这个修正过的宏,这个函数将会return,这显然是你不希望这个宏做的事情。

解决方案
  1. 标准数学库已经有pow的版本。
  2. 定义宏为内联函数:

  inline int Power(int a, int b) {
    int result = 1; 
    for (int i = 0; i < b; ++i) result *= a; 
    return result;
  }

最新更新