2014-09-13 71 views
-5

下面的程序是打印49從#定義SQR(X)(X * X)

#include <stdio.h> 
#define SQR(x) (x*x) 
void main(void) { 
    int x, y; x = 5; 
    y = SQR(++x); 
    printf("y is %d\n", y); 
} 

我不明白我錯過了什麼不正確的答案。
這裏就是我理解它是如何可能的工作
SQR(++x)++x將被評估爲6x*x36應返回。
因此y = 36
但答案是

+2

想想宏如何工作以及表達式評估的次數。 – 2014-09-13 10:37:07

+0

@Matt:不,它本身不是未定義的。 – usr2564301 2014-09-13 10:38:36

+0

@Jongware是的,它是 – 2014-09-13 10:38:58

回答

5

閱讀有關C preprocessor的wiki,瞭解C預處理器在純文本級別(作爲編譯器的第一階段)運行。另請參閱GNU cpp文檔。您的y = SQR(++x);展開爲

y = ++x * ++x; 

這不是您應該想要的。閱讀關於undefined behavior(和this answer)。 想想發生的恐怖事件(使用您的原始SQR)與SQR(y+3)

看看你的源代碼的預處理形式。隨着GCC,使用

gcc -C -E foo.c > foo.i 

獲得進入foo.ifoo.c

所以預處理的形式,至少是(你應該用編輯器或尋呼機檢查),你應該定義宏爲

#define SQR(x) ((x)*(x)) 

否則SQR(y+3)將不會像您想要的那樣展開。一般來說,在使用宏時,你應該知道(並且記錄,例如在評論中,如果你正在編寫宏)發生了什麼事情。

事實上,在你的情況,你不應該在所有使用宏,而是定義inline function

static inline int square(int x) { return x*x; } 

這將是一樣快,您的宏,但更安全,因爲square(++x)將增加(正確)x只有一次,而square(y+3)正在做你想做的!

2

請記住,宏替換幾乎一字不差,這意味着你的

SQR(++x); 

++x * ++x; 

而且,作爲替代由dyp指出,這是未定義的行爲。