宏的意外行为
Unexpected behavior of macro
#include<bits/stdc++.h>
#define f(a,b) a*b
using namespace std;
int main()
{cout<<f(2*2,3*2);
return 0;
}
输出 24 而
#include<bits/stdc++.h>
#define f(a,b) a*b
using namespace std;
int main()
{cout<<f(2+1,3+1);
return 0;
}
输出 6.
如何解释宏的这种繁忙行为?我使用代码块。
提前致谢。
宏是文本替换,因此您的第二个片段集变为:
cout<<2+1 * 3+1
已解析
cout<< 2 + (1 *3) + 1
在你的情况下使用函数而不是宏:
int f(int a, int b) { return a * b; }
宏是一种简单的文本替换机制。在您的示例中,您有以下宏:
#define f(a,b) a*b
当您使用该宏时,文本 a*b
被替换为宏调用,用您用作参数的任何内容替换 a
和 b
。
在您的第一个示例中,f(2*2,3*2)
变为 2*2*3*2
,它会按照您的预期输出 24。但是,在您的第二个示例中,f(2+1,3+1)
变为 2+1*3+1
,被解释为 2+(1*3)+1
并因此输出 6.
您可以通过不同方式定义宏来解决此问题:
#define f(a,b) ((a)*(b))
注意多出的一组括号。这确保宏在表达式中的任何其他内容之前被评估。 a
和 b
周围的额外括号确保首先评估参数。
操作的优先级可以随宏改变。在你的例子中,它不发送 3 和 4,它实际上发送 1+2 和 1+3,它像这样扩展:
1+2*1+3
不过,这种东西并不真正属于宏。如果你有 c++11,你可以使用 constexpr:
constexpr int f(int a, int b) {
return a*b;
}
如果您希望使用运行时值获得更好的运行时性能,而 c++11 不是一个选项,您可以强制内联函数:
inline int f(int a, int b) {
return a*b;
}
我
你的问题是宏是邪恶的原因之一。只要可以,就不要使用它,只有在它是唯一的解决方案时才使用它们。
#include<bits/stdc++.h>
#define f(a,b) a*b
using namespace std;
int main()
{cout<<f(2*2,3*2);
return 0;
}
输出 24 而
#include<bits/stdc++.h>
#define f(a,b) a*b
using namespace std;
int main()
{cout<<f(2+1,3+1);
return 0;
}
输出 6.
如何解释宏的这种繁忙行为?我使用代码块。 提前致谢。
宏是文本替换,因此您的第二个片段集变为:
cout<<2+1 * 3+1
已解析
cout<< 2 + (1 *3) + 1
在你的情况下使用函数而不是宏:
int f(int a, int b) { return a * b; }
宏是一种简单的文本替换机制。在您的示例中,您有以下宏:
#define f(a,b) a*b
当您使用该宏时,文本 a*b
被替换为宏调用,用您用作参数的任何内容替换 a
和 b
。
在您的第一个示例中,f(2*2,3*2)
变为 2*2*3*2
,它会按照您的预期输出 24。但是,在您的第二个示例中,f(2+1,3+1)
变为 2+1*3+1
,被解释为 2+(1*3)+1
并因此输出 6.
您可以通过不同方式定义宏来解决此问题:
#define f(a,b) ((a)*(b))
注意多出的一组括号。这确保宏在表达式中的任何其他内容之前被评估。 a
和 b
周围的额外括号确保首先评估参数。
操作的优先级可以随宏改变。在你的例子中,它不发送 3 和 4,它实际上发送 1+2 和 1+3,它像这样扩展:
1+2*1+3
不过,这种东西并不真正属于宏。如果你有 c++11,你可以使用 constexpr:
constexpr int f(int a, int b) {
return a*b;
}
如果您希望使用运行时值获得更好的运行时性能,而 c++11 不是一个选项,您可以强制内联函数:
inline int f(int a, int b) {
return a*b;
}
我
你的问题是宏是邪恶的原因之一。只要可以,就不要使用它,只有在它是唯一的解决方案时才使用它们。