2016-03-08 136 views
0

我想实现一个调试打印机制,它允许运行时和编译时过滤。过滤是通过一个热门编码掩码完成的。通过宏过滤

运行时过滤通过检查函数中的掩码来完成。如果该级别当前未设置,则返回。编译时实际上会删除对调试打印的调用。

编译时间可以很容易地实现。

#include <stdio.h> 

#define PRINT_LEVEL_0 (0x0) 
#define PRINT_LEVEL_1 (0x1) 
#define PRINT_LEVEL_2 (0x2) 
#define PRINT_LEVEL_3 (0x4) 
#define PRINT_LEVEL_4 (0x8) 

#define PRINT_COMPILE_LEVEL (PRINT_LEVEL_1 | PRINT_LEVEL_3 | PRINT_LEVEL_4) 

#define PRINT(printLevel, ...) \ 
    printLevel ## _FILTER(__VA_ARGS__) 

#define PRINT_LEVEL_0_FILTER(...)   // Compile out 

#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_1) 
    #define PRINT_LEVEL_1_FILTER(...)  printf(__VA_ARGS__) 
#else 
    #define PRINT_LEVEL_1_FILTER(...)  // Compile out 
#endif 

#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_2) 
    #define PRINT_LEVEL_2_FILTER(...)  printf(__VA_ARGS__) 
#else 
    #define PRINT_LEVEL_2_FILTER(...)  // Compile out 
#endif 

#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_3) 
    #define PRINT_LEVEL_3_FILTER(...)  printf(__VA_ARGS__) 
#else 
    #define PRINT_LEVEL_3_FILTER(...)  // Compile out 
#endif 

#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_4) 
    #define PRINT_LEVEL_4_FILTER(...)  printf(__VA_ARGS__) 
#else 
    #define PRINT_LEVEL_4_FILTER(...)  // Compile out 
#endif 


int main(void) 
{ 
    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST NO ARGS\n"); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST ONE ARGS %u\n", 1); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST TWO ARGS %u %u\n", 1, 2); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST THREE ARGS %u %u %u\n", 1, 2, 3); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST FOUR ARGS %u %u %u %u\n", 1, 2, 3, 4); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST ONE ARGS %s\n", "Garfield"); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST TWO ARGS %s %s\n", "Garfield", "likes"); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST THREE ARGs %s %s %s\n", "Garfield", "likes", "eating"); 

    PRINT(PRINT_LEVEL_3, 
      "PRINT_TEST FOUR ARGS %s %s %s %s\n", "Garfield", "likes", "eating", "lasagna"); 

    return 0; 
} 

如果有效PRINT_LEVEL_#预处理器被作为第一个输入参数到PRINT宏提供这只能。

如果printLevel ## _FILTER不存在,我有兴趣找到调用其他宏的方法(对运行时筛选有效)。确切的情况是这样的:

void foo() 
{ 
    uint32_t level = PRINT_LEVEL_3; 

    PRINT(level, "VARIABLE LEVEL TEST"); 
} 

感谢您的帮助!

+0

要明确的,那把foo()functino内,例如不工作的原因是因为“level_FILTER”宏不存在。 – trialUnplugged

+0

这似乎是不可能*这种方式。 –

+0

为什么你不能使用像'void print(int levels,const char * str [levels])'这样的函数?太类型安全和太可读?你可以这样调用它,例如:'print(3,&(const char * str [3]){“Garfield”,“hates”,“macros”});' – Lundin

回答

1

如果您信任编译器检测常量表达式,这将会简单得多。你可以只使用“运行时”if,以便在编译时条件具有已知值的情况下,编译器将避免进行测试(并且如果条件已知为条件执行代码假)。因为几乎所有的现代编译器都没有遇到这种优化问题,所以它不应该很难假设它会发生。

然后你只需要

#define PRINT(level, ...) \ 
    do if (level & LEVEL_MASK) \ 
    printf(__VA_ARGS__); while (0)