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

时间:2014-08-14 23:51:24

标签: c++ macros expression c-preprocessor

我试图做这种定义:

#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))

但我得到了同样的错误。

3 个答案:

答案 0 :(得分:3)

您不能在宏名称中放置.个字符。即使可以,宏内的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);

答案 1 :(得分:1)

除了名称中的.问题之外,您的宏还引入了多个与括号分组的语句,例如: (声明;声明;声明;)这不是合法的C / C ++语法。但是,您可以使用comma operator来评估多个单独的表达式(但不能执行多个任意语句)。然而,有更好的方法可以做你正在尝试做的事情。

答案 2 :(得分:1)

讨论

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

您的第一个问题是您的宏名称包含一个点.。这是不允许的,因为宏的名称是标识符。标识符名称不允许使用点字符,因为.用于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;}
}

上面的代码在语法上是正确的,但它有一个逻辑缺陷。来自return的{​​{1}} s result。这意味着如果你在一个函数中声明了这个更正的宏,这个函数将main,这显然是你不会想要这个宏来做。

解决方案

  1. 标准数学库已具有pow的版本。
  2. 将宏定义为内联函数:

  3. return