C++ / C #define 宏计算

C++ / C #define macro calculation

假设我有

#define DETUNE1 sqrt(7)-sqrt(5)
#define DETUNE2 sqrt(11)-sqrt(7)

我在我的程序中多次调用这些。

DETUNE1 和 DETUNE2 是否在每次 调用时计算

是的,#define 只是将短语的每个实例替换为您定义的内容

当编译器编译您的程序时,在它进行任何插入之前,有一个称为预处理的阶段。在此阶段,编译器将盲目地将所有#define 实例替换为它们的定义,因此代码中使用 DETUNE1 的每个地方都将简单地替换为 sqrt(7)-sqrt(5),这当然是一种计算

您可以使用变量来预缓存此值,或者更好 - 自己计算并将其存储在定义中,如下所示:

sqrt(7)-sqrt(5) = 0.409

所以

#define DETUNE1 0.409

这是最有效的方法 - 完全避免计算。

有关 gcc 中 C 宏的更多信息,请参见此处:https://gcc.gnu.org/onlinedocs/cpp/Macros.html#Macros

每次都会计算。最好你 #define 计算值。您还需要确保将它们放在括号中,因为它可能会产生意想不到的结果。

例如如果您在计算中使用如下:

int result = DETUNE1 * 4

那么它将导致

int result = sqrt(7)-sqrt(5) * 4

因为operator precedence in C

所以乘法会在减法之前完成

#define 以文本方式替换您的宏声明,因此每次您编写 : DETUNE1 时,如果您多次编写 DETUNE1,则 sqrt(7)-sqrt(5) 会代替 it.So 进行多次评估.

是的 - 避免宏的另一个原因(好像我们还需要)。使用 consts 代替:

const double DETUNE1 = sqrt(7) - sqrt(5);
const double DETUNE2 = sqrt(11) - sqrt(7);

Are DETUNE1 and DETUNE2 calculated every time it is called?

极不可能

因为您使用常量调用 sqrt,大多数编译器会优化对 sqrt 函数的调用并将其替换为常量值。 GCC 在 -O1 上执行此操作。 clang也是。 (See live).

在一般情况下,如果您有一个将 n 作为运行时值的宏:

#define DETUNE1(n) (sqrt(n)-sqrt(n))

那么在文本替换之后,至少sqrt函数需要计算。

请注意您的宏安全。为了安全起见,你应该在它周围加上括号。例如,因为 DETUNE1 * DETUNE1 不会产生您期望的结果。