假設我們有這樣的表達:C++定義表達式求值
#define cube(x) x * x * x
然後我們把它叫做:
int n = 3, v;
v = cube(n + 1); // v = 10
v = cube((n + 1)); // v = 64
v = cube(n); // v = 27
所以,問題是:爲什麼第一個操作不作v = 64
?
假設我們有這樣的表達:C++定義表達式求值
#define cube(x) x * x * x
然後我們把它叫做:
int n = 3, v;
v = cube(n + 1); // v = 10
v = cube((n + 1)); // v = 64
v = cube(n); // v = 27
所以,問題是:爲什麼第一個操作不作v = 64
?
宏未評估(在評估的常見解釋意義上),它們在編譯時被擴展。
文件編譯之前,還有被稱爲C Preprocessor另一個程序,它取代了宏調用字面上/文本方式並準備實際編譯的文件,所以您的宏
#define cube(x) x * x * x when you do this
這
v = cube(n + 1);
被替換爲(展開的是正確的術語)
v = n + 1 * n + 1 * n + 1;
// Simplifies to
v = n + n + n + 1;
// and again
v = 3 * n + 1;
這對於n = 3
給你10
完全觀察到的結果。
注意,當您添加括號
v = cube((n + 1));
然後,擴展
v = (n + 1) * (n + 1) * (n + 1);
這是你所期望的cube()
做,所以防止這種情況,你應該重新定義宏這樣
#define cube(x) ((x) * (x) * (x))
如果您使用的是GCC嘗試
gcc -E source.c
並檢查結果,以驗證該宏是如何擴大。
@iharob:很好的答案。您可能會添加有關多次評估的潛在問題的警告。 – chqrlie
@tomab,這是純粹的文本替換,如果您嘗試使用帶有副作用的宏來擴展宏,它會讓您感到更加驚訝。 – StoryTeller
只是一個挑剔的問題:宏觀/文本擴展*是一種評估形式,雖然它不是大多數人所想的形式(並且重要的是,它不是根據C++的規則進行的評估,也不是常規代數的評估)。 –
閱讀有關運算符優先級的內容。手動展開MACRO並檢查。 –
這必須是重複的... – chqrlie
@chqrlie我懷疑,但我找不到類似的東西。 – tomab