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_LOGENABLE_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 语句中抑制有关常量条件的警告。