博客專欄

EEPW首頁 > 博客 > c語言宏定義##__VA_ARGS__封裝printf函數(shù),單片機(jī)實(shí)現(xiàn)簡單的分級日志模塊

c語言宏定義##__VA_ARGS__封裝printf函數(shù),單片機(jī)實(shí)現(xiàn)簡單的分級日志模塊

發(fā)布人:電子禪石 時(shí)間:2023-02-20 來源:工程師 發(fā)布文章

在單片機(jī)開發(fā)中經(jīng)常需要加入printf之類的函數(shù)來輸出調(diào)試信息,這些信息一般伴隨著整個(gè)開發(fā)過程,但是在程序發(fā)布時(shí)候,又得將它們注釋掉,非常的不方便,于是有了以下解決辦法:


使用宏定義開關(guān)

 #ifdef __DEBUG
 #define DEBUG(info)    printf(info)
 #else
 #define DEBUG(info)
 #endif

但是這樣并不能發(fā)揮出printf函數(shù)的強(qiáng)大功能,使用起來并不方便。


使用不定參數(shù)的宏定義


c99規(guī)范后,編譯器就開始支持不定參數(shù)##__VA_ARGS__的宏定義

相關(guān)知識(shí)可參考博客http://blog.csdn.net/aobai219/archive/2010/12/22/6092292.aspx

于是我們就有了這樣的一個(gè)宏定義

————————————————

 #ifdef __DEBUG
 #define DEBUG(format, ...) printf (format, ##__VA_ARGS__)
 #else
 #define DEBUG(format, ...)
 #endif

嗯,現(xiàn)在printf的功能是有了,那干脆再輸出一些相關(guān)的信息,這樣一下子就可以知道代碼位置,然后就變成這樣了:


 #ifdef __DEBUG
     #define DEBUG(format, ...) \
          printf("FILE: "__FILE__", LINE: %d: "format"/n", __LINE__,##__VA_ARGS__)
 #else
     #define DEBUG(format, ...)
 #endif

調(diào)試信息會(huì)按照下面格式輸出
FILE: xxx, LINE: xxx, …….

到這邊似乎都挺完美了,可還有一個(gè)問題,這邊的調(diào)試開關(guān)是全局的,可是有時(shí)候我們只關(guān)心某一模塊的調(diào)試信息,要是能屏蔽無關(guān)的信息那就好了,那我們再做一點(diǎn)功課,簡單的實(shí)現(xiàn)日志分級,以下是代碼實(shí)現(xiàn):

/*
 * logger.h
 *
 *  Created on: 2018年01月28日
 *      Author: dj666
 */

#ifndef APP_PUBLIC_LOGGER_H_
#define APP_PUBLIC_LOGGER_H_

#define __DEBUG    //日志模塊總開關(guān),注釋掉將關(guān)閉日志輸出

#ifdef __DEBUG
    #define DEBUG(format, ...) printf (format, ##__VA_ARGS__)
#else
    #define DEBUG(format, ...)
#endif

//定義日志級別
enum LOG_LEVEL {    
    LOG_LEVEL_OFF=0,
    LOG_LEVEL_FATAL,
    LOG_LEVEL_ERR,
    LOG_LEVEL_WARN,
    LOG_LEVEL_INFO,
    LOG_LEVEL_ALL,
};

#define log_fatal(level,format, ...) \
    do { \
         if(level>=LOG_LEVEL_FATAL)\
           DEBUG("\n->FATAL @ FUNC:%s FILE:%s LINE:%d \n" format "\n",\
                     __func__, __FILE__, __LINE__, ##__VA_ARGS__ );\
    } while (0)

#define log_err(level,format, ...) \
    do { \
         if(level>=LOG_LEVEL_ERR)\
           DEBUG("\n->ERR   @ FUNC:%s FILE:%s LINE:%d \n" format "\n",\
                     __func__, __FILE__, __LINE__, ##__VA_ARGS__ );\
    } while (0)

#define log_warn(level,format, ...) \
    do { \
         if(level>=LOG_LEVEL_WARN)\
           DEBUG("\n->WARN  @ FUNC:%s \n" format "\n",__func__, ##__VA_ARGS__ );\
    } while (0)

#define log_info(level,format, ...) \
    do { \
         if(level>=LOG_LEVEL_INFO)\
           DEBUG("\n->INFO  \n"format"\n",##__VA_ARGS__ );\
    } while (0)

#define log_debug(level,format, ...) \
    do { \
         if(level>=LOG_LEVEL_ALL)\
           DEBUG("\n->DEBUG \n"format"\n",##__VA_ARGS__ );\
    } while (0)

#endif /* APP_PUBLIC_LOGGER_H_ */


使用也非常簡單,定義一個(gè)局部的變量來保存該模塊的日志輸出級別,下面是使用示例:

#include"logger.h"

static enum LOG_LEVEL logger=LOG_LEVEL_WARN;//模塊日志輸出級別

int main(void)
{ 
    logger = LOG_LEVEL_ALL; //修改模塊日志輸出級別
    log_debug(logger,"this is a debug");
    log_info(logger,"this is a info");
    log_warn(logger,"%s","this is a warn");
    log_err(logger,"this is a err %d ",-1);
}


c語言宏定義##__VA_ARGS__封裝printf函數(shù),單片機(jī)實(shí)現(xiàn)簡單的分級日志模塊_昵稱隨便取啦的博客-CSDN博客

*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。



關(guān)鍵詞: c

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉