Enable/Disable 使用 C 宏的日志级别
Enable/Disable LOG levels using C Macro
#include <stdio.h>
#define LOG_D(x) { printf("D:"); printf(x);}
#define LOG_E(x) { printf("E:"); printf(x);}
void test(void)
{
LOG_D("ALL is well " );
}
我有一个非常庞大的代码,它有不同级别的日志,就像上面的代码一样。
在最终测试的库中,我只需要一个错误日志来减少代码大小。
所以我想要这样的东西
#define ENABLE_DEBUG_LOG 0
#define ENABLE_ERROR_LOG 1
#define LOG_D(x) {#if(ENABLE_DEBUG_LOG==1) printf("D:"); printf(x); #endif}
#define LOG_E(x) {#if(ENABLE_ERROR_LOG==1) printf("E:"); printf(x);#endif}
我添加这个 #if(ENABLE_DEBUG_LOG==1) 只是为了解释,我需要一些可以编译的解决方案。
您应该可以这样做:
#if ENABLE_DEBUG_LOG == 1
# define LOG_D(x) { printf("D:"); printf(x);}
#else
# define LOG_D(x)
#end
这样,如果 ENABLE_DEBUG_LOG
未定义或具有不同的值,调试日志语句将消失。
您不能嵌套预处理器指令。但是您可以制作两个版本的宏并在 #if
或 #ifdef
:
的独占部分中定义它们
#define ENABLE_DEBUG_LOG 0
#if ENABLE_DEBUG_LOG != 0
#define LOG_D(...) printf("D: " __VA_ARGS__)
#else
#define LOG_D(...) // Do nothing
#endif
在这里,禁用版本只是 "eats" LOG_D
宏,什么都不做。 (请注意,未定义的宏在 #if
条件中被视为值 0。)
我不确定这是否是您想要的,但您可以查看 #ifdef
指令。
#include <stdio.h>
/* #define DEBUG */
#ifdef DEBUG
#define LOG_D(x) { printf("D: %s\n",x); }
#define LOG_E(x) { printf("E: %s\n",x); }
#else
#define LOG_D(x)
#define LOG_E(x)
#endif
int main() {
LOG_D("blah...");
return 0;
}
如果取消注释 #define DEBUG
行,程序将打印 D: blah...
另一种选择 - 您可以只注释/取消注释 ENABLE_DEBUG_LOG
和 ENABLE_ERROR_LOG
以禁用/启用相应的日志级别。
// #define ENABLE_DEBUG_LOG // disable DEBUG_LOG
#define ENABLE_ERROR_LOG // enable ERROR_LOG
#ifdef ENABLE_DEBUG_LOG
#define LOG_D(x) { printf("D:"); printf(x);}
#else
#define LOG_D(x) // nothing
#endif
#ifdef ENABLE_ERROR_LOG
#define LOG_E(x) { printf("E:"); printf(x);}
#else
#define LOG_E(x) // nothing
#endif
关于其他答案,在未启用时将宏定义为完全空不是一个好主意,因为在启用错误日志记录时这会出错:
if (some_error)
LOG_E("Oops...");
do_something();
如果 LOG_E(x)
展开为空,那么 do_something()
只会在 some_error
为真时被调用,这可能不是您想要的!
因此您可以像这样定义 LOG_E(x)
的 "do nothing" 变体:
#define LOG_E(x) { }
我倾向于使用 do { blah; } while (0)
结构,而不是用大括号开始和结束,因为它会强制您在使用它时在末尾加上分号。像这样:
#if ENABLE_ERROR_LOG
#define LOG_E(x) do { printf("E:"); printf(x); } while (0)
#else
#define LOG_E(x) do ; while (0)
#endif
然后,
if (some_error)
LOG_E("Oops")
会因为缺少分号而导致语法错误,迫使您将其写成
if (some_error)
LOG_E("Oops");
您可以做的另一件事是将 "E:"
或 "D:"
标记与传入的字符串连接起来,尽管这要求参数是字符串文字,而不是一般的 char *
:
#define LOG_E(x) printf("E:" x)
您可以做的另一件事是使用可变数量的参数定义宏(variadic 宏)以增加您的选择:
#define LOG_E(...) printf("E:" __VA_ARGS__)
那么你可以这样做:
if (some_error)
LOG_E("Oops, got error: %d\n", some_error);
您可以做的另一件事是让编译器优化对 printf
的调用并像这样定义它:
#define LOG_E(...) do if (ENABLE_ERROR_LOG) printf("E:" __VA_ARGS__); while (0)
一个体面的编译器会注意到 if
条件是常量,并且要么完全优化对 printf
的调用(如果常量条件为假),要么包括它(如果常量条件是真的)。对于某些编译器,您可能需要在 if
语句中抑制有关常量条件的警告。
#include <stdio.h>
#define LOG_D(x) { printf("D:"); printf(x);}
#define LOG_E(x) { printf("E:"); printf(x);}
void test(void)
{
LOG_D("ALL is well " );
}
我有一个非常庞大的代码,它有不同级别的日志,就像上面的代码一样。 在最终测试的库中,我只需要一个错误日志来减少代码大小。
所以我想要这样的东西
#define ENABLE_DEBUG_LOG 0
#define ENABLE_ERROR_LOG 1
#define LOG_D(x) {#if(ENABLE_DEBUG_LOG==1) printf("D:"); printf(x); #endif}
#define LOG_E(x) {#if(ENABLE_ERROR_LOG==1) printf("E:"); printf(x);#endif}
我添加这个 #if(ENABLE_DEBUG_LOG==1) 只是为了解释,我需要一些可以编译的解决方案。
您应该可以这样做:
#if ENABLE_DEBUG_LOG == 1
# define LOG_D(x) { printf("D:"); printf(x);}
#else
# define LOG_D(x)
#end
这样,如果 ENABLE_DEBUG_LOG
未定义或具有不同的值,调试日志语句将消失。
您不能嵌套预处理器指令。但是您可以制作两个版本的宏并在 #if
或 #ifdef
:
#define ENABLE_DEBUG_LOG 0
#if ENABLE_DEBUG_LOG != 0
#define LOG_D(...) printf("D: " __VA_ARGS__)
#else
#define LOG_D(...) // Do nothing
#endif
在这里,禁用版本只是 "eats" LOG_D
宏,什么都不做。 (请注意,未定义的宏在 #if
条件中被视为值 0。)
我不确定这是否是您想要的,但您可以查看 #ifdef
指令。
#include <stdio.h>
/* #define DEBUG */
#ifdef DEBUG
#define LOG_D(x) { printf("D: %s\n",x); }
#define LOG_E(x) { printf("E: %s\n",x); }
#else
#define LOG_D(x)
#define LOG_E(x)
#endif
int main() {
LOG_D("blah...");
return 0;
}
如果取消注释 #define DEBUG
行,程序将打印 D: blah...
另一种选择 - 您可以只注释/取消注释 ENABLE_DEBUG_LOG
和 ENABLE_ERROR_LOG
以禁用/启用相应的日志级别。
// #define ENABLE_DEBUG_LOG // disable DEBUG_LOG
#define ENABLE_ERROR_LOG // enable ERROR_LOG
#ifdef ENABLE_DEBUG_LOG
#define LOG_D(x) { printf("D:"); printf(x);}
#else
#define LOG_D(x) // nothing
#endif
#ifdef ENABLE_ERROR_LOG
#define LOG_E(x) { printf("E:"); printf(x);}
#else
#define LOG_E(x) // nothing
#endif
关于其他答案,在未启用时将宏定义为完全空不是一个好主意,因为在启用错误日志记录时这会出错:
if (some_error)
LOG_E("Oops...");
do_something();
如果 LOG_E(x)
展开为空,那么 do_something()
只会在 some_error
为真时被调用,这可能不是您想要的!
因此您可以像这样定义 LOG_E(x)
的 "do nothing" 变体:
#define LOG_E(x) { }
我倾向于使用 do { blah; } while (0)
结构,而不是用大括号开始和结束,因为它会强制您在使用它时在末尾加上分号。像这样:
#if ENABLE_ERROR_LOG
#define LOG_E(x) do { printf("E:"); printf(x); } while (0)
#else
#define LOG_E(x) do ; while (0)
#endif
然后,
if (some_error)
LOG_E("Oops")
会因为缺少分号而导致语法错误,迫使您将其写成
if (some_error)
LOG_E("Oops");
您可以做的另一件事是将 "E:"
或 "D:"
标记与传入的字符串连接起来,尽管这要求参数是字符串文字,而不是一般的 char *
:
#define LOG_E(x) printf("E:" x)
您可以做的另一件事是使用可变数量的参数定义宏(variadic 宏)以增加您的选择:
#define LOG_E(...) printf("E:" __VA_ARGS__)
那么你可以这样做:
if (some_error)
LOG_E("Oops, got error: %d\n", some_error);
您可以做的另一件事是让编译器优化对 printf
的调用并像这样定义它:
#define LOG_E(...) do if (ENABLE_ERROR_LOG) printf("E:" __VA_ARGS__); while (0)
一个体面的编译器会注意到 if
条件是常量,并且要么完全优化对 printf
的调用(如果常量条件为假),要么包括它(如果常量条件是真的)。对于某些编译器,您可能需要在 if
语句中抑制有关常量条件的警告。