2015-02-08 27 views
-1

我碰到一個項目來了一架C性向問題網站爲什麼宏的值在被調用函數中沒有變化?

#define i 20 

void fun(); 

int main(void) 
{ 
    printf("%d..",i); 
    fun(); 
    printf("%d",i);  
} 

void fun() { 
#undef i; 
#define i 30 
} 

這裏的輸出變成

20..20 

但據我來說,這應該是

20..30 

爲什麼多申」 t i的值在撥打fun()後變爲30?

#define i 20 

void fun(); 
int main(void) 
{ 
printf("%d..",i); 
#define i 50  
printf("%d",i);  
} 

但是,如果我編譯並運行上述程序的輸出變成20..50 那麼現在怎麼宏值在運行時更改。

+0

答案在於預處理器和編譯器之間的區別。搜索網絡的一些信息,它應該很清楚。 – 2015-02-08 13:43:59

+0

在運行程序之前,甚至在編譯之前處理宏。讓你的編譯器寫出「預處理」的代碼,你會看到「我」做什麼。 (另外:絕對不要在「define」中包含分號,用你明顯的經驗水平,你**會得到一些令人討厭的驚喜!) – usr2564301 2015-02-08 13:45:52

回答

5

宏在運行時無法更改。在你的程序中,宏在編譯之前由預處理器改變一次,所以它在編譯的程序中的值是30

你可以閱讀關於它here

void fun() { 
#undef i; 
#define i 30 
} 

實際上是一個空函數,預處理程序將

void fun(); 
int main(void) 
{ 
    printf("%d..",20); 
    fun(); 
    printf("%d",20); 
} 
void fun() { 
} 

,所以你可以看到,輸出是正確的。

要生成你可以用gcc

gcc -E -P source.c 

使用上述預處理程序實際上是一個空函數

+0

但是如果你喜歡printf(「%d ..」,i); #define i 50 printf(「%d」,i);輸出變爲20..50 – 2015-02-08 13:44:31

+0

'#define i 50 printf(「%d」,i)'?完全像那樣?如果您有這樣的情況,請將其添加到您的問題中,以幫助您解釋實際發生的情況。 – 2015-02-08 13:46:11

+3

甚至在編譯器在運行時間之前看到代碼之前,宏也被替換(如純文本替換)與它們的定義。如果您重新定義了一個宏,那麼對於代碼文件中低於重定義的所有代碼,其值將會改變,但是它之前沒有。如果你把一個'printf(「%d \ n」,i);在第二個'#define'之後的'fun'中,你會得到輸出'20 50 20'。 – Wintermute 2015-02-08 13:52:40

3

的proprocessor的指示是完全獨立的,獨立於程序的普通流。原因在於在C標準中指定的翻譯階段。處理階段(階段1-4)在正確彙編(階段7)之前在概念上進行。預處理階段後獲得的單位被稱爲翻譯單位,您可以將其作爲進一步翻譯的「起點」,包括正確的編譯。

您的編譯器可能允許檢查特定的翻譯單元,因此您可以看到它的效果。例如gcc-E標誌(默認情況下,它輸出所謂的linemarkers,但您可以使用-P標誌禁止它們)。在你的情況下,它可能看起來像:

$ gcc -E test.c 
# 1 "test.c" 
# 1 "<built-in>" 
# 1 "<command-line>" 
# 1 "test.c" 


void fun(); 

int main(void) 
{ 
    printf("%d..",20); 
    fun(); 
    printf("%d",20); 
} 

test.c:13:9: warning: extra tokens at end of #undef directive 
void fun() { 


} 
相關問題