2015-06-23 33 views
2

假設我有C++/C#定義的宏計算

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

而且我在程序中調用這些多次。

DETUNE1和DETUNE2是否計算它被調用的時間?

回答

6

是否DETUNE1和DETUNE2計算每次調用的時間呢?

非常不可能

由於您使用常量調用sqrt,因此大多數編譯器會優化對sqrt函數的調用並將其替換爲常量值。海灣合作委員會在-O1。叮噹聲。(See live)。

在一般情況下,如果你有n是一個運行值的宏:

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

則文本替換後,的sqrt功能至少一個需要計算。

請注意,您的宏是而不是安全。你應該在它周圍有括號以保證安全。例如,因爲DETUNE1 * DETUNE1不會產生您所期望的。

+0

Thanks.Didn't知道。用常量調用的每個函數都以這種方式替換嗎? –

+0

對於使用常量調用的每個庫函數,它都沒有*保證*,但大多數編譯器會盡可能在編譯時進行常量計算。 –

+0

您提出了一個很好的觀點,即編譯器非常聰明,通常會優化它;然而,這不是保證它會被優化。由於它是直接的文本替換,因此編譯器可以決定在某些情況下對其進行優化,而不是在其他情況下對其進行優化。 –

1

是的是的話,使用#define只是替換詞組的每一個實例與您定義什麼

當編譯器編譯你的程序,它的任何interpertation之前還有一個叫預處理階段。在這個階段,編譯器會盲目地將所有#define實例替換爲它們的定義,因此代碼中使用DETUNE1的每個地方都將被sqrt(7)-sqrt(5)替換,這是計算過程

可以使用一個變量來預緩存此值,或者更好的 - 自己進行計算,並將其存儲在一個定義,像這樣:

sqrt(7)-sqrt(5) = 0.409

所以

#define DETUNE1 0.409

這是最有效的方法 - 完全避免計算。

在這裏看到關於C宏的進一步信息在GCC:https://gcc.gnu.org/onlinedocs/cpp/Macros.html#Macros

+1

只有3位數字?這不是很精確。 – MSalters

3

它每次都會被計算。計算的值更好的是#define。您還需要確保將它們放在括號內,因爲它可能會帶來意想不到的結果。

例如如果您使用的計算如下:

int result = DETUNE1 * 4 

那麼就會導致

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

所以乘法將減法之前因爲operator precedence in C

2

#定義的文本形式代替您的宏聲明,以便完成每次寫入:DETUNE1,sqrt(7)-sqrt(5)代替它。因此,如果您多次寫入DETUNE1,將會完成多個評估。

0

是的 - 避免宏的另一個原因(如果我們需要更多)。使用const!而非:

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

有很多使用宏的原因。在C/C++編寫時,如果不是必要的話,它們可能非常有用,即使它們可能不是這種情況下的最佳選擇。 –

+0

@pcluddite:我不會說很多原因 - 有一些特定情況下宏有意義,但一般情況下,他們應該避免絕大多數情況下,例如定義常量(如這裏的情況),內聯函數等等,這裏有更好的選擇。 –

+0

我認爲使用宏與'const's最大的好處之一是宏*是一個直接的文本替換。如果你的代碼中需要重用的值,使用宏可以放棄不必要的內存分配,並確保它不會像其他任何類型一樣處理。 –