最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析在C/C++中如何寫(xiě)調(diào)試宏

 更新時(shí)間:2024年05月02日 08:35:08   作者:wangxinzhi  
這篇文章主要為大家詳細(xì)介紹了在C/C++中如何寫(xiě)調(diào)試宏的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下

1. 調(diào)試宏以及測(cè)試

在寫(xiě)代碼時(shí),不可避免需要打印提示、警告、錯(cuò)誤等信息,且要靈活控制打印信息的級(jí)別。另外,還有可能需要使用宏來(lái)控制代碼段(主要是調(diào)試代碼段)是否執(zhí)行。為此,本文提供一種調(diào)試宏定義方案,包括打印字符串信息LOG1宏和格式化打印LOG2宏,且能通過(guò)宏控制代碼段執(zhí)行。完整代碼如下:

#ifndef __DEBUG_H__
#define __DEBUG_H__

#include <iostream>
#include <string>
#include <stdio.h>

// 定義日志級(jí)別枚舉
enum LogLevel
{
    DEBUG,
    INFO,
    WARN,
    ERROR,
    FATAL
};

// 全局日志級(jí)別變量聲明
extern LogLevel globalLogLevel;

// 定義日志宏1
#define LOG1(level, message) do { \
    if (level >= globalLogLevel) { \
        std::cout << "[" #level "] " << __func__ << ":" << __LINE__ << " " << message << std::endl; \
    } \
} while (0)

// 定義日志宏2
// stdout帶緩沖,按行刷新,fflush(stdout)強(qiáng)制刷新
// stderr不帶緩沖,立刻刷新到屏幕
#define LOG2(level, format, args...) do { \
    if (level >= globalLogLevel) { \
        fprintf(stderr, "[" #level "] %s:%d " format "\r\n", __func__, __LINE__, ##args); \
    } \
} while (0)

// 通過(guò)宏控制調(diào)試代碼是否執(zhí)行
#define EXECUTE

#ifdef EXECUTE
#define DEBUG_EXECUTE(code) [code]
#else
#define DEBUG_EXECUTE(code)
#endif

#endif

在main文件進(jìn)行宏定義測(cè)試,需要定義全局日志級(jí)別,以INFO為例,則DEBUG信息不打印。測(cè)試文件如下:

#include "debug.h"

// 全局日志級(jí)別變量定義
LogLevel globalLogLevel = INFO;

int main(void)
{
    LOG1(DEBUG, "DEBUG message");
    LOG1(INFO, "INFO message");
    LOG1(WARN, "WARN message");
    LOG1(ERROR, "ERROR message");
    LOG1(FATAL, "FATAL message");

    int num = 10;
    LOG2(INFO, "num: %d", num);

    DEBUG_EXECUTE(
        LOG2(ERROR, "debug execute");
    )
}

2. 宏定義小細(xì)節(jié)

2.1 #和##

兩者都是預(yù)處理運(yùn)算符

  • #是字符串化運(yùn)算符,將其后的宏參數(shù)轉(zhuǎn)換為用雙括號(hào)括起來(lái)的字符串。
  • ##是符號(hào)連接運(yùn)算符,用于連接兩個(gè)標(biāo)記(標(biāo)記不一定是宏變量,可以是標(biāo)識(shí)符、關(guān)鍵字、數(shù)字、字符串、運(yùn)算符)為一個(gè)標(biāo)記。

在第一章中使用#把日志級(jí)別變量轉(zhuǎn)為字符串,##的作用是在可變參數(shù)為0是,刪除前面的逗號(hào),只輸出字符串。

2.2 do while(0)

do while常用來(lái)做循環(huán),而while參數(shù)為0,表示這樣的代碼肯定不是做循環(huán)用的,它有什么用呢?

輔助定義復(fù)雜宏,避免宏替換出錯(cuò)

假如你定義一個(gè)這樣宏,本意是調(diào)用DOSOMETHING時(shí)執(zhí)行兩個(gè)函數(shù)。

#define DOSOMETHING() \
			func1(); \
			func2();

但在類似如下使用宏的代碼,宏展開(kāi)時(shí)func2無(wú)視判斷條件都會(huì)執(zhí)行。

if (0 < a)
	DOSOMETHING();

// 宏展開(kāi)后
if (0 < a)
    func1();
func2();

優(yōu)化一下,用{}包裹宏是否可行呢?如下:

#define DOSOMETHING() { \
			func1(); \
			func2();}

由于我們寫(xiě)代碼習(xí)慣在語(yǔ)句后加分號(hào),你可能會(huì)有如下的展開(kāi)后編譯錯(cuò)誤。

if(0 < a)
    DOSOMETHING();
else
   ...

// 宏展開(kāi)后

if(0 < a)
{
    func1();
    func2();
}; // 錯(cuò)誤處
else
    ...

而do while (0)則能避免這些錯(cuò)誤,所以復(fù)雜宏定義經(jīng)常使用它。

消除分支語(yǔ)句或者goto語(yǔ)句,提高代碼的易讀性

如果在一個(gè)函數(shù)中開(kāi)始要分配一些資源,然后在中途執(zhí)行過(guò)程中如果遇到錯(cuò)誤則退出函數(shù),當(dāng)然,退出前先釋放資源,我們的代碼可能是這樣:

bool Execute()
{
   // 分配資源
   int *p = new int;
   bool bOk(true);
 
   // 執(zhí)行并進(jìn)行錯(cuò)誤處理
   bOk = func1();
   if(!bOk) 
   {
      delete p;   
      p = NULL;
      return false;
   }
 
   bOk = func2();
   if(!bOk) 
   {
      delete p;   
      p = NULL;
      return false;
   }
 
   // 執(zhí)行成功,釋放資源并返回
    delete p;   
    p = NULL;
    return true;
   
}

這里一個(gè)最大的問(wèn)題就是代碼的冗余,而且我每增加一個(gè)操作,就需要做相應(yīng)的錯(cuò)誤處理,非常不靈活。于是我們想到了goto:

bool Execute()
{
   // 分配資源
   int *p = new int;
   bool bOk(true);
 
   // 執(zhí)行并進(jìn)行錯(cuò)誤處理
   bOk = func1();
   if(!bOk) goto errorhandle;
 
   bOk = func2();
   if(!bOk) goto errorhandle;
 
   // 執(zhí)行成功,釋放資源并返回
    delete p;   
    p = NULL;
    return true;
 
errorhandle:
    delete p;   
    p = NULL;
    return false;
   
}

代碼冗余是消除了,但是我們引入了C++中身份比較微妙的goto語(yǔ)句,雖然正確的使用goto可以大大提高程序的靈活性與簡(jiǎn)潔性,但太靈活的東西往往是很危險(xiǎn)的,它會(huì)讓我們的程序捉摸不定,那么怎么才能避免使用goto語(yǔ)句,又能消除代碼冗余呢,請(qǐng)看do...while(0)

bool Execute()
{
   // 分配資源
   int *p = new int;
 
   bool bOk(true);
   do
   {
      // 執(zhí)行并進(jìn)行錯(cuò)誤處理
      bOk = func1();
      if(!bOk) break;
 
      bOk = func2();
      if(!bOk) break;
 
   }while(0);
 
    // 釋放資源
    delete p;   
    p = NULL;
    return bOk;
   
}

使用代碼塊,代碼塊內(nèi)定義變量,不用考慮變量重復(fù)問(wèn)題

顯而易見(jiàn)。

到此這篇關(guān)于淺析在C/C++中如何寫(xiě)調(diào)試宏 的文章就介紹到這了,更多相關(guān)C++寫(xiě)調(diào)試宏 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言函數(shù)的基本使用和遞歸小結(jié)

    C語(yǔ)言函數(shù)的基本使用和遞歸小結(jié)

    這篇文章主要介紹了C語(yǔ)言函數(shù)的基本使用和遞歸小結(jié),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • C++構(gòu)造函數(shù)初始化順序詳解

    C++構(gòu)造函數(shù)初始化順序詳解

    這篇文章主要介紹了C++構(gòu)造函數(shù)初始化順序詳解,是對(duì)C++代碼的運(yùn)行機(jī)制深入探討,需要的朋友可以參考下
    2014-10-10
  • MinGW-w64 C/C++編譯器下載和安裝的方法步驟(入門(mén)教程)

    MinGW-w64 C/C++編譯器下載和安裝的方法步驟(入門(mén)教程)

    如果電腦沒(méi)有安裝MinGW-w64 C/C++編譯器,就無(wú)法運(yùn)行g(shù)cc命令,本文主要介紹了MinGW-w64 C/C++編譯器下載和安裝的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • c++ 虛繼承,多繼承相關(guān)總結(jié)

    c++ 虛繼承,多繼承相關(guān)總結(jié)

    這篇文章主要介紹了c++虛繼承,多繼承相關(guān)總結(jié),幫助大家更好的理解和學(xué)習(xí)使用c++,感興趣的朋友可以了解下
    2021-03-03
  • Qt實(shí)現(xiàn)刪除布局與布局切換功能

    Qt實(shí)現(xiàn)刪除布局與布局切換功能

    在Qt應(yīng)用開(kāi)發(fā)中,動(dòng)態(tài)管理布局是一個(gè)常見(jiàn)需求,比如根據(jù)用戶操作動(dòng)態(tài)刪除某個(gè)布局,或在不同布局間進(jìn)行切換,本文將詳細(xì)介紹如何實(shí)現(xiàn)這些功能,并通過(guò)完整示例展示具體操作,需要的朋友可以參考下
    2025-11-11
  • C++中volatile關(guān)鍵字及常見(jiàn)的誤解總結(jié)

    C++中volatile關(guān)鍵字及常見(jiàn)的誤解總結(jié)

    這篇文章主要給大家介紹了關(guān)于C++中volatile關(guān)鍵字及常見(jiàn)的誤解的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • C++超詳細(xì)講解單鏈表的實(shí)現(xiàn)

    C++超詳細(xì)講解單鏈表的實(shí)現(xiàn)

    單鏈表是后面要學(xué)的雙鏈表以及循環(huán)鏈表的基礎(chǔ),要想繼續(xù)深入了解數(shù)據(jù)結(jié)構(gòu)以及C++,我們就要奠定好這塊基石!接下來(lái)就和我一起學(xué)習(xí)吧
    2022-03-03
  • Qt學(xué)習(xí)教程之對(duì)話框消失動(dòng)畫(huà)效果

    Qt學(xué)習(xí)教程之對(duì)話框消失動(dòng)畫(huà)效果

    這篇文章主要給大家介紹了關(guān)于Qt學(xué)習(xí)教程之對(duì)話框消失動(dòng)畫(huà)效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • C++結(jié)構(gòu)體案例練習(xí)分享

    C++結(jié)構(gòu)體案例練習(xí)分享

    這篇文章主要和大家分享幾個(gè)C++?結(jié)構(gòu)體的案例練習(xí),幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下,希望能夠給你帶來(lái)幫助
    2022-04-04
  • 純C++代碼詳解二叉樹(shù)相關(guān)操作

    純C++代碼詳解二叉樹(shù)相關(guān)操作

    二叉樹(shù)(Binary?tree)是樹(shù)形結(jié)構(gòu)的一個(gè)重要類型。許多實(shí)際問(wèn)題抽象出來(lái)的數(shù)據(jù)結(jié)構(gòu)往往是二叉樹(shù)形式。本文將通過(guò)代碼為大家詳細(xì)講講C++二叉樹(shù)的一些常規(guī)操作,感興趣的可以學(xué)習(xí)一下
    2022-07-07

最新評(píng)論

合江县| 龙泉市| 昭平县| 额敏县| 当雄县| 龙岩市| 育儿| 曲阳县| 宾阳县| 汽车| 和政县| 平阳县| 泾川县| 深泽县| 金川县| 揭东县| 化州市| 北票市| 定陶县| 乡城县| 恩施市| 贵阳市| 镇平县| 措美县| 高雄县| 普兰店市| 东丰县| 平昌县| 小金县| 湖北省| 大理市| 双江| 于田县| 延长县| 浙江省| 灵丘县| 论坛| 高雄县| 扎鲁特旗| 彩票| 乐昌市|