使用C宏启用/禁用LOG级别

时间:2015-12-10 10:20:54

标签: c macros

#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)只是为了解释,我需要一些可以编译的解决方案。

5 个答案:

答案 0 :(得分:5)

另一个选项 - 您只需评论/取消注释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

答案 1 :(得分:4)

您无法嵌套预处理程序指令。但您可以制作两个版本的宏,并在#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

在这里,禁用版只是&#34;吃&#34; LOG_D宏,并没有做任何事情。 (请注意,未定义的宏在#if条件中被视为值0。)

答案 2 :(得分:3)

你应该可以这样做:

#if ENABLE_DEBUG_LOG == 1
#    define LOG_D(x)  {  printf("D:");  printf(x);}
#else
#    define LOG_D(x)
#end

这样,如果ENABLE_DEBUG_LOG未定义或具有不同的值,调试日志语句就会消失。

答案 3 :(得分:1)

我不确定这是否是您想要的,但您可以查看#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...

答案 4 :(得分:1)

关于其他答案,在未启用宏时将宏定义为完全空是不明智的,因为在启用错误日志记录时会出错:

    if (some_error)
        LOG_E("Oops...");
    do_something();

如果LOG_E(x)扩展为空,那么只有在do_something()为真时才会调用some_error,这可能不是您想要的!

所以你可以像这样定义LOG_E(x)的“无所事事”变体:

#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)

您可以做的另一件事是使用可变数量的参数(可变参数宏)定义宏以增加选项:

#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语句中禁止有关常量条件的警告。