2016-03-08 171 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)