【问题标题】:Filtering via macros通过宏过滤
【发布时间】:2016-03-08 14:48:48
【问题描述】:

我想实现一个允许运行时和编译时过滤的调试打印机制。过滤是通过 one-hot 编码掩码完成的。

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

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

#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" );
}

感谢您的帮助!

【问题讨论】:

  • 明确地说,foo() 函数中的示例不起作用的原因是“level_FILTER”宏不存在。
  • 看来不可能this这样。
  • 有什么理由不能使用像 void print (int levels, const char* str [levels]) 这样的函数?类型太安全且可读性太强?你可以这样称呼它,例如:print(3, &amp;(const char* str[3]) {"Garfield", "hates", "macros"} );

标签: c macros c-preprocessor variadic-macros


【解决方案1】:

如果您信任编译器来检测常量表达式,这会简单得多。您可以放心地使用“运行时”if,如果条件具有在编译时已知的值,编译器将避免进行测试(如果条件已知,则进一步消除有条件执行的代码是假的)。

由于几乎所有现代编译器都没有遇到这种优化问题,因此不难假设它会发生。

那么你只需要

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2015-08-28
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    相关资源
    最近更新 更多