2011-03-19 93 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); 

希望这有助于