通过宏过滤
Filtering via macros
我想实现一个允许 运行 时间和编译时间过滤的调试打印机制。过滤是通过单热编码掩码完成的。
运行-时间过滤是通过检查函数内的掩码来完成的。如果当前未设置级别 returns。编译时实际上删除了对调试打印的调用。
编译时间很容易实现。
#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" );
}
感谢您的帮助!
如果您信任编译器检测常量表达式,这会简单得多。你可以只使用 "run-time" if
来安慰一下,如果条件在编译时有一个已知的值,编译器将避免进行测试(并进一步消除条件执行的代码,如果条件已知是假的)。
由于几乎所有现代编译器都可以轻松应对这种优化,因此不难假设它会发生。
那么你只需要
#define PRINT(level, ...) \
do if (level & LEVEL_MASK) \
printf(__VA_ARGS__); while (0)
我想实现一个允许 运行 时间和编译时间过滤的调试打印机制。过滤是通过单热编码掩码完成的。
运行-时间过滤是通过检查函数内的掩码来完成的。如果当前未设置级别 returns。编译时实际上删除了对调试打印的调用。
编译时间很容易实现。
#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" );
}
感谢您的帮助!
如果您信任编译器检测常量表达式,这会简单得多。你可以只使用 "run-time" if
来安慰一下,如果条件在编译时有一个已知的值,编译器将避免进行测试(并进一步消除条件执行的代码,如果条件已知是假的)。
由于几乎所有现代编译器都可以轻松应对这种优化,因此不难假设它会发生。
那么你只需要
#define PRINT(level, ...) \
do if (level & LEVEL_MASK) \
printf(__VA_ARGS__); while (0)