<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
"); //-->

博客專(zhuān)欄

EEPW首頁(yè) > 博客 > c語(yǔ)言宏定義##__VA_ARGS__封裝printf函數,單片機實(shí)現簡(jiǎn)單的分級日志模塊

c語(yǔ)言宏定義##__VA_ARGS__封裝printf函數,單片機實(shí)現簡(jiǎn)單的分級日志模塊

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

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


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

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

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


使用不定參數的宏定義


c99規范后,編譯器就開(kāi)始支持不定參數##__VA_ARGS__的宏定義

相關(guān)知識可參考博客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

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


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

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

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

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

#ifndef APP_PUBLIC_LOGGER_H_
#define APP_PUBLIC_LOGGER_H_

#define __DEBUG    //日志模塊總開(kāi)關(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_ */


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

#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語(yǔ)言宏定義##__VA_ARGS__封裝printf函數,單片機實(shí)現簡(jiǎn)單的分級日志模塊_昵稱(chēng)隨便取啦的博客-CSDN博客

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



關(guān)鍵詞: c

相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>