我已經在頭文件中使用預處理宏在我的代碼中添加了一堆「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$
無關,但從技術上說,並且通過規範,具有兩個前導下劃線的符號保留供編譯器和標準庫使用。 – 2014-10-11 23:13:38
爲了記錄目的使用這種宏的一個小技巧: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
@datenwolf現在我在我的可變參數宏中使用了## __ VA_ARGS__(即__VA_ARGS__前面有兩個#符號),它似乎與-std = gnu99一起工作。你預見到這個組合有任何問題嗎? (目前我只是一個C學生,並且還沒有碰到交叉編譯器問題。) – iceman 2014-10-12 00:07:49