-3

我刚开始学习c++。原谅这样的问题。我的任务是编写一个宏来计算周长并测试它。

#define _USE_MATH_DEFINES
#include <cmath>

#define LENGTH(radius) (2 * M_PI * radius)

float l1 = LENGTH(1 + 2); // The result should be 18.8495... I have 8.28. Incorrect result.
float l2 = 1 / LENGTH(2); // The result should be  0.07957... Working correctly.

我添加了额外的括号:

float l1 = LENGTH((1 + 2)); // Correct result.

如何在不添加额外括号的情况下编写这样的宏来获得正确的结果?

4

3 回答 3

12

利用:

#define LENGTH(radius) (2 * M_PI * (radius))

当你写

float l1 = LENGTH(1 + 2);

使用您定义的预处理器将其转换为

float l1 = 2 * M_PI * 1 + 2
于 2013-01-01T12:46:49.700 回答
3

总是,总是,将宏参数包裹起来()——不管它看起来多么微不足道,你迟早会需要它。

当然,编写一个做同样事情的函数有几个好处: 1. 你可以在调试器中单步执行它,这样你就可以真正弄清楚发生了什么。2. 宏参数表达式没有奇怪之处。

为了解释第二点,假设我们有这个代码使用你的宏:

 // Print 10 lengths, 3, 5, 7, ... 
 int x = 3;
 for(i = 0; i < 10; i++)
 {
      printf("Length of radius %d is %5.2f\n", x, LENGTH(x += 2));
 }

现在,有人参加了优化课程,并意识到 2* 某事比某事 + 某事更快,因此将您的宏重写为更快:

 #define LENGTH(radius) (((radius) + (radius)) * M_PI)

现在,由于我们x+=2LENGTH宏中,发生了奇怪的事情(它变成了未定义的行为,因为同一个变量在同一个语句中更新了两次[是的,我的意思是在两个序列点之间]。如果有一个length函数,它会完美地工作你会期待的。

于 2013-01-01T13:01:00.050 回答
1

不要为此使用宏——内联函数在各方面都更好

但是发生的事情很容易理解,理解为什么最好避免使用宏很有用。

#define LENGTH(radius) (2 * M_PI * radius)

float l1 = LENGTH(1 + 2);

宏只是简单的文本替换,因此上面的代码被替换为:

float l1 = (2 * M_PI * 1 + 2);

这显然具有错误的运算符优先级。

于 2013-01-01T17:07:45.360 回答