C/C++可變參數,「## __VA_ARGS__」宏的介紹和使用

下面是C99的方法:編程

1 #define dgbmsg(fmt,...)     printf(fmt,__VA_ARGS__)

代碼函數

#include <stdarg.h>
#include <stdio.h>
#define LOGSTRINGS(fm, ...) printf(fm,__VA_ARGS__) 
int main()
{
    LOGSTRINGS("hello, %d ", 10);
    return 0;
}

自定義調試信息的輸出.net

  調試信息的輸出方法有不少種,  例如直接用printf,  或者出錯時使用perror, fprintf等將信息直接打印到終端上, 在Qt上面通常使用qDebug,而守護進程則通常是使用syslog將調試信息輸出到日誌文件中等等...
  使用標準的方法打印調試信息有時候不是很方便,  例如Qt編程, 在調試已有的代碼時, 我想在打印調試信息的地方, 把代碼位置也打印出來以方便定位錯誤, 或者須要在調試信息前面加一個前輟, 好方便在調試信息太多的時候能夠用grep過濾一下, 僅顯示本模塊的調試信息, 這時就須要一個一個地修改已有的qDebug, 使其成爲如下形式:
  qDebug( "[模塊名稱] 調試信息  File:%s, Line:%d", __FILE__, __LINE__ );
  這樣的修改比較煩人, 並且一不當心會遺漏某個沒改的...
  爲了能方便地管理調試信息的輸出,一個比較簡單的方法就是自已定義一個打印調試信息的宏, 而後替換原來的,廢話就很少說了,直接給出一個現成的,下面是一個例子, 我用WiFi表示當前代碼的模塊名稱,我要求在模塊中的全部調試信息前面均帶有[WiFi]前輟,這樣我就能方便地只需使用命令行 | grep "
WiFi
WiFi
"來過濾掉來自其它模塊的調試信息了:
#define qWiFiDebug(format, ...) qDebug("[WiFi] "format" File:%s, Line:%d, Function:%s", ##__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__);
  上面的宏是使用qDebug輸出調試信息,在非Qt的程序中也能夠改成printf,守護進程則能夠改成syslog等等...  其中,決竅其實就是這幾個宏 ##__VA_ARGS__, __FILE__, __LINE__ 和__FUNCTION__,下面介紹一下這幾個宏:
  1)  __VA_ARGS__ 是一個可變參數的宏,不多人知道這個宏,這個可變參數的宏是新的C99規範中新增的,目前彷佛只有gcc支持(VC6.0的編譯器不支持)。宏前面加上##的做用在於,當可變參數的個數爲0時,這裏的##起到把前面多餘的","去掉的做用,不然會編譯出錯, 你能夠試試。
  2) __FILE__ 宏在預編譯時會替換成當前的源文件名
  3) __LINE__宏在預編譯時會替換成當前的行號
  4) __FUNCTION__宏在預編譯時會替換成當前的函數名稱
  有了以上這幾個宏,特別是有了__VA_ARGS__ ,調試信息的輸出就變得靈活多了。
  有時,咱們想把調試信息輸出到屏幕上,而有時則又想把它輸出到一個文件中,可參考下面的例子:
//debug.c
#include <stdio.h>
#include <string.h>
//開啓下面的宏表示程序運行在調試版本, 不然爲發行版本, 這裏假設只有調試版本才輸出調試信息
#define _DEBUG
#ifdef _DEBUG
    //開啓下面的宏就把調試信息輸出到文件,註釋即輸出到終端
    #define DEBUG_TO_FILE
    #ifdef DEBUG_TO_FILE
        //調試信息輸出到如下文件
        #define DEBUG_FILE "/tmp/debugmsg"
        //調試信息的緩衝長度
        #define DEBUG_BUFFER_MAX 4096
        //將調試信息輸出到文件中
        #define printDebugMsg(moduleName, format, ...) {\
            char buffer[DEBUG_BUFFER_MAX+1]={0};\
            snprintf( buffer, DEBUG_BUFFER_MAX \
                    , "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );\
            FILE* fd = fopen(DEBUG_FILE, "a");\
            if ( fd != NULL ) {\
                fwrite( buffer, strlen(buffer), 1, fd );\
                fflush( fd );\
                fclose( fd );\
            }\
        }
    #else
        //將調試信息輸出到終端
        #define printDebugMsg(moduleName, format, ...) \
                  printf( "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );
    #endif //end for #ifdef DEBUG_TO_FILE
#else
    //發行版本,什麼也不作
    #define printDebugMsg(moduleName, format, ...)
#endif  //end for #ifdef _DEBUG
int main(int argc, char** argv)
{
    int data = 999;
    printDebugMsg( "TestProgram", "data = %d", data );
    return 0;
}
 
 
  上面也說了,只有支持C99規範的gcc編譯器纔有__VA_ARGS__這個宏,若是不是gcc編譯器,或者所用的gcc編譯器版本不支持__VA_ARGS__宏怎麼辦? 可參考下面的代碼片斷,咱們換一種作法,可先將可變參數轉換成字符串後,再進行輸出便可:
void printDebugMsg( const char* format, ...)
{
    char buffer[DEBUG_BUFFER_MAX_LENGTH + 1]={0};
    va_list arg;
    va_start (arg, format);
    vsnprintf(buffer, DEBUG_BUFFER_MAX_LENGTH, format, arg);
    va_end (arg);
    printf( "%s", buffer );
}
--------------------- 
做者:bat67 
來源:CSDN 
原文:https://blog.csdn.net/bat67/article/details/77542165 
版權聲明:本文爲博主原創文章,轉載請附上博文連接!命令行

相關文章
相關標籤/搜索