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 进行多次评估.
是的 - 避免宏的另一个原因(好像我们还需要)。使用 const
s 代替:
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
不会产生您期望的结果。
假设我有
#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 进行多次评估.
是的 - 避免宏的另一个原因(好像我们还需要)。使用 const
s 代替:
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
不会产生您期望的结果。