2011-03-19 111 views
0

這裏是我的宏的一個樣本:在宏上運行的預處理宏?

#define STR(val) #val 
#define STRX(val) STR(val) 
#define LINE_ STRX(__LINE__) 
#define SRC_STR __FILE__":"LINE_ 
#define SRC_STRN SRC_STR"\n" 

#define PRINT_IF(cond) ((cond)&&(printf("\""#cond"\" is true: "SRC_STRN)>=0)) 
#define PRINT_IFNOT(cond) ((!(cond))&&(printf("\""#cond"\" is false: "SRC_STRN)>=0)) 
#define PRINT_IFN PRINT_IFNOT 
#define PRINT_IFEQ(a,b) PRINT_IF(a==b) 

#define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val) 
#define PRINT_INT(i) PRINT_FMT(i,%d) 
#define PRINT_LONG(i) PRINT_FMT(i,%ld) 
#define PRINT_UINT(i) PRINT_FMT(i,%u) 
#define PRINT_ULONG(i) PRINT_FMT(i,%lu) 
#define PRINT_HEX(i) PRINT_FMT(i,%x) 
#define PRINT_FLT(flt) PRINT_FMT(flt,%g) 
#define PRINT_PTR(ptr) PRINT_FMT(ptr,%p) 
#define PRINT_STR(str) PRINT_FMT(str,%s) 

我想定義與此相關的一個宏的另一份名單,但我想,以避免鍵入的一切。我已經寫了一個例子:

#ifndef UNITTEST 
#define PRINT_INT_U(x) ((void)sizeof(x)) 
#else 
#define PRINT_INT_U(x) PRINT_INT(x) 
#endif 

你可以看到,我想我的PRINT_ ... _U功能,以評估沒事的時候我沒有運行單元測試,這樣我就可以杜絕垃圾郵件,而不用擔心他們在調試或生產過程中到處跳出來。

所以我的問題是,是否有使用預處理產生新的#define語句一些瘋狂的方法?我的猜測是,有沒有...

編輯:我可以至少做這樣的事情嗎?做一個清單:

INT 
LONG 
UINT 
ULONG 
HEX 
FLT 
PTR 
STR 

,然後他們都各插入模式

#define PRINT_%LI%_U(x) PRINT_%LI%(x) 

其中%LI%代表列表中的項目。

+0

您在尋找LISP/Scheme嗎? – Mehrdad 2011-03-19 03:31:04

回答

0

怎麼是這樣的:

#include <stdio.h> 

#define FLAG 

#ifdef FLAG 
#define SW(x,...) x##_1(__VA_ARGS__) 
#else 
#define SW(x,...) x##_0(__VA_ARGS__) 
#endif 

#define TEST1(a) SW(TEST1,a) 
#define TEST1_0(a) 10 
#define TEST1_1(a) 11 

#define TEST2(a,b) SW(TEST2,a,b) 
#define TEST2_0(a,b) 20 
#define TEST2_1(a,b) 21 

#define TEST3() 32 

int main(void) { 

    printf("1. TEST1 = %i\n", TEST1(1)); 
    printf("2. TEST2 = %i\n", TEST2(1,2)); 
    printf("3. TEST3 = %i\n", TEST3()); 

} 

其可以通過參數數量而不是可變宏來定義SW1,SW2等。

我希望它足夠清晰的,它可以定義SW()來普遍禁用所有 宏,具體取決於標誌值。但宏「定義」(通過SW)和「實現」仍然需要不同的名稱(沒有「宏重載」),並且它不可能將#define放入宏中。

但是它肯定沒有必要爲每個宏編寫單獨的#ifdef。

1

您不需要更改所有PRINT_TYPE宏的定義:因爲它們都委託給PRINT_FMT,所以您只需更改該宏的定義即可。

#ifndef UNITTEST 
    #define PRINT_FMT(unused, unused) 0 
#else 
    #define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val) 
#endif 

printf返回int,所以對於一致性是有意義的具有無操作版本具有類型int。)

+0

我認爲編譯器會警告'語句對'0;'這樣的語句沒有任何效果。您可以提出一個關於我可以利用的PRINT_FMT依賴關係的優點。不過,我仍然需要所有額外的'_U'宏,所以我可以有兩個版本。我仍然想在我的非單元測試版本中使用它們。 – 2011-03-19 03:29:45

+0

@Steven:我會簡單地'#define PRINT_FMT(未使用,未使用)',這樣它就會展開爲空。 – 2011-03-19 11:23:26

0

雖然不是很令人滿意,至少,下面的代碼重用 格式說明符部分。 我不知道這可以真正幫助你,但萬一這可能是一個暗示:

#define INT %d 
#define LONG %ld 
...and so forth... 

#define PRINT(val,fmt) printf(#val" = "STRX(fmt)": "SRC_STRN,val) 

#ifndef UNITTEST 
#define PRINT_U(x,fmt) ((void)sizeof(x)) 
#else 
#define PRINT_U(x,fmt) PRINT(x,fmt) 
#endif 

    int i; 
    long l; 
    PRINT(i, INT); 
    PRINT(l, LONG); 
    PRINT_U(i, INT); 

希望這有助於