2014-10-11 45 views
0

我已經在頭文件中使用預處理宏在我的代碼中添加了一堆「debug(x)」語句。我還實現了一個切換(通過頭文件中的#ifdef/#else結構),可以讓我關閉調試語句。我無法使此切換開始工作,並希望有人能夠找出原因。C:對預處理宏的困惑

而不是重新發布實際的代碼(這是很長的),我包括一個說明性的例子(它編譯)。

這是我們的.h文件。它由一個名爲「超人」的函數組成。當且僅當KRYPTONITE沒有在我們的.c文件中定義時,該語句應該打印。

test.h:

#ifndef __test_h__ 
#define __test_h__ 

#ifdef KRYPTONITE 
#define superman(...) 
#else 
#define superman(xs) printf("%s\n\n",xs) 
#endif 

#endif 

正如你可以在下面的情況看,加入了「的#define KRYPTONITE 1」的聲明對我們的.c文件的開頭不切換掉了「超人」功能(下面的案例2)。但是,如果我們通過編譯指令中的一個標誌定義KRYPTONITE,則我們確實成功切換(情況3)。

爲了通過.c文件中的「#define」語句關閉「超人」功能,還需要做些什麼?例1:KRYPTONITE沒有在.c文件中定義(它被註釋掉了)。正如預期的那樣,該聲明將被打印(.c文件和輸出低於。)

test1.c:

#include <stdio.h> 
#include "test.h" 
//#define KRYPTONITE 

int main (int argc, char *argv[]) 
{ 
    printf("\nSuperman, are you here?\n\n"); 
    superman("I'm here"); 
    return 0; 
} 

輸出:

[email protected]:~/SO$ gcc test1.c -o test1 
[email protected]:~/SO$ ./test1 

Superman, are you here? 
I'm here 

[email protected]:~/SO$ 

情況2:KRYPTONITE是在我們的.c文件定義但聲明打印。

test2.c中:

#include <stdio.h> 
#include "test.h" 

#define KRYPTONITE 

int main (int argc, char *argv[]) 
{ 
    printf("\nSuperman, are you here?\n\n"); 
    superman("I'm here"); 
    return 0; 
} 

輸出:

[email protected]:~/SO$ gcc test2.c -o test2 
[email protected]:~/SO$ ./test2 

Superman, are you here? 
I'm here 

[email protected]:~/SO$ 

案例3:KRYPTONITE不在我們的.c文件中定義的,而是通過一個標誌編譯時,我們把它定義。在這種情況下,超人功能被成功切換。

輸出:

[email protected]:~/SO$ gcc -DKRYPTONITE test1.c -o test3 
[email protected]:~/SO$ ./test3 

Superman, are you here? 

[email protected]:~/SO$ 
+3

無關,但從技術上說,並且通過規範,具有兩個前導下劃線的符號保留供編譯器和標準庫使用。 – 2014-10-11 23:13:38

+1

爲了記錄目的使用這種宏的一個小技巧:C99預處理器支持可變宏,MSVC也有它們。方式略有差異,處理擴展中的尾隨逗號。例如'#define log_printf(l,fmt,...)fprintf(stderr,「%c:」fmt,l,__VA_ARGS __)「。然而,對於GCC,這需要始終提供額外的參數,MSVC默默解決了這種情況。不過,GCC的擴展名可以寫成'#__ VA_ARGS__'。 – datenwolf 2014-10-11 23:22:17

+0

@datenwolf現在我在我的可變參數宏中使用了## __ VA_ARGS__(即__VA_ARGS__前面有兩個#符號),它似乎與-std = gnu99一起工作。你預見到這個組合有任何問題嗎? (目前我只是一個C學生,並且還沒有碰到交叉編譯器問題。) – iceman 2014-10-12 00:07:49

回答

2

的proeprocessor,就像C編譯器,掃描文件,從頂部到底部。這意味着在使用之前,宏必須定義爲

所以要解決您的問題,請在之前加#define

#include <stdio.h> 

#define KRYPTONITE 

#include "test.h" 

int main (int argc, char *argv[]) 
{ 
    printf("\nSuperman, are you here?\n\n"); 
    superman("I'm here"); // Doesn't print 
    return 0; 
} 
+0

添加了代碼示例來說明。 – 2014-10-11 23:16:26