亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

#ifndef __DEBUG_H__
#define __DEBUG_H__

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

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

// 全局日志級別變量聲明
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)強制刷新
// stderr不帶緩沖,立刻刷新到屏幕
#define LOG2(level, format, args...) do { \
    if (level >= globalLogLevel) { \
        fprintf(stderr, "[" #level "] %s:%d " format "\r\n", __func__, __LINE__, ##args); \
    } \
} while (0)

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

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

#endif

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

#include "debug.h"

// 全局日志級別變量定義
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. 宏定義小細節(jié)

2.1 #和##

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

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

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

2.2 do while(0)

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

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

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

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

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

if (0 < a)
	DOSOMETHING();

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

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

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

由于我們寫代碼習(xí)慣在語句后加分號,你可能會有如下的展開后編譯錯誤。

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

// 宏展開后

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

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

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

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

bool Execute()
{
   // 分配資源
   int *p = new int;
   bool bOk(true);
 
   // 執(zhí)行并進行錯誤處理
   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;
   
}

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

bool Execute()
{
   // 分配資源
   int *p = new int;
   bool bOk(true);
 
   // 執(zhí)行并進行錯誤處理
   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語句,雖然正確的使用goto可以大大提高程序的靈活性與簡潔性,但太靈活的東西往往是很危險的,它會讓我們的程序捉摸不定,那么怎么才能避免使用goto語句,又能消除代碼冗余呢,請看do...while(0)

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

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

顯而易見。

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

相關(guān)文章

  • c語言10個經(jīng)典小程序

    c語言10個經(jīng)典小程序

    c語言的經(jīng)典程序,學(xué)習(xí)c語言的初學(xué)者可以參考下
    2013-01-01
  • C++浮點型的存儲方式詳解

    C++浮點型的存儲方式詳解

    本篇文章是對C/C++浮點數(shù)在內(nèi)存中的存儲方式進行了詳細的分析介紹,需要的朋友參考下,希望能夠給你帶來幫助
    2021-09-09
  • C++實現(xiàn)頭文件保護機制

    C++實現(xiàn)頭文件保護機制

    頭文件保護機制是一種防止頭文件被重復(fù)包含的技術(shù),它主要借助 #ifndef、#define 和 #endif 這些預(yù)處理指令來達成,本文就來詳細的介紹一下,感興趣的可以了解一下
    2025-04-04
  • C語言入門篇--局部全局變量的作用域及生命周期

    C語言入門篇--局部全局變量的作用域及生命周期

    本篇文章是c語言基礎(chǔ)篇,本文對初識c語言的變量、局部全局變量的作用域及生命周期做了簡要的概述,希望可以幫助大家快速入門c語言的世界,更好的理解c語言
    2021-08-08
  • C語言之system函數(shù)案例詳解

    C語言之system函數(shù)案例詳解

    這篇文章主要介紹了C語言之system函數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 淺談C語言轉(zhuǎn)義字符和格式控制符

    淺談C語言轉(zhuǎn)義字符和格式控制符

    下面小編就為大家?guī)硪黄獪\談C語言轉(zhuǎn)義字符和格式控制符。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • c++ vector模擬實現(xiàn)的全過程

    c++ vector模擬實現(xiàn)的全過程

    這篇文章主要給大家介紹了關(guān)于c++ vector的模擬實現(xiàn)過程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 詳解C++ new-handler機制

    詳解C++ new-handler機制

    這篇文章主要介紹了C++ new-handler機制的相關(guān)資料,幫助大家更好的理解和使用c++,感興趣的朋友可以了解下
    2020-11-11
  • C語言學(xué)生信息管理系統(tǒng)設(shè)計與實現(xiàn)

    C語言學(xué)生信息管理系統(tǒng)設(shè)計與實現(xiàn)

    這篇文章主要為大家詳細介紹了C語言學(xué)生信息管理系統(tǒng)設(shè)計與實現(xiàn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 實例講解C++編程中的虛函數(shù)與虛基類

    實例講解C++編程中的虛函數(shù)與虛基類

    這篇文章主要介紹了C++編程中的虛函數(shù)與虛基類的實例講解,虛函數(shù)與虛基類的使用是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2016-02-02

最新評論