嗨,宏問題
有人能幫我理解爲什麼SQUARE(x)的值是49嗎?
我正在使用Visual C++ 6.0。
#define SQUARE(X) X * X
int main(int argc, char* argv[])
{
int y = 5;
printf("%d\n",SQUARE(++y));
return 0;
}
嗨,宏問題
有人能幫我理解爲什麼SQUARE(x)的值是49嗎?
我正在使用Visual C++ 6.0。
#define SQUARE(X) X * X
int main(int argc, char* argv[])
{
int y = 5;
printf("%d\n",SQUARE(++y));
return 0;
}
尼爾巴特沃斯,馬克和帕維爾是正確的。
SQUARE(++ y)擴展爲++ y * ++ y,它將y的值增加兩倍。 (a + b)不是(a + b)*(a + b),而是a +(b * a)+ b擴展到a + b * a + b。在定義宏時,您應該注意在需要時在元素周圍添加括號:#define SQUARE(X)((X)*(X))風險較小。 (伊恩·肯普在他的評論中第一次寫的)
你也可以使用內聯模板函數(沒有在運行時效率較低),像這樣的:
template <class T>
inline T square(T value)
{
return value*value;
}
您可以檢查它的工作原理:
int i = 2;
std::cout << square(++i) << " should be 9" << std::endl;
std::cout << square(++i) << " should be 16" << std::endl;
(沒有必要寫
square<int>(++i)
因爲int類型是隱含的對於i)
因爲宏展開:
++y * ++y
,其給出了C++未定義行爲 - 其結果可能 是任何東西。這個衆所周知的問題應該涵蓋任何涵蓋宏使用的正派教科書。你在使用哪一個?
你也可以看到6x7 = 42,這取決於你的編譯器。 – 2009-08-29 10:21:24
@願意 - 或者你可能沒有得到42. – 2009-08-29 21:26:48
因爲宏做文本替換,所以你寫的代碼被擴大到
printf("%d\n",++y * ++y);
,然後操作的順序是不確定的行爲,使這個編譯器看到2個增量,然後乘
所以要謹慎使用宏,以便使用函數,因爲編譯器可以擴展內聯,不再需要運行。
其次不要以爲你增加會發生什麼,並使用變量
宏不是函數:他們只是改變了程序的文本。該操作被稱爲預處理,並且在編譯代碼之前它會自動執行。人們編寫宏以節省時間並在源代碼中引入一些可變性。
當您編寫SQUARE(x)
時,不會發生實際的功能調用,只是文本被修改。操作非常笨拙,所以你必須在像你這樣的情況下采取額外的預防措施。請參閱其他答案以解釋您的案例。
啊,這個老栗子......要得到你應該使用的正確結果:#define SQUARE(X)((X)*(X))。 – 2009-08-29 10:28:16
@我錯了,恐怕。 – 2009-08-29 10:32:56
Ian Kemp的評論確實是錯誤的,因爲它沒有解決問題。但是,在宏中,更好的方法是添加括號:SQUARE(a + b)擴展爲不是(a + b)*(a + b)的a + b * a + b,而是a +(b * a)+ b。 – moala 2009-08-29 11:02:18