va_start()va_end()和vsnprintf()函數應用

   通常我們需要在程序中輸出部分日誌信息,並把它記錄到文件中。在這種情況下,使用printf可以爲我們帶了很大方便。因爲printf卻省情況下是向stdout即控制檯屏幕輸出信息,在GUI程序中,我們看不到printf的輸出結果,但是我們可以將該輸出重定向到指定的文件中。即使用freopen(“c://yourlog.log”, “a+”,stdout)或通過yourapp.exe > c:/yourlog.log完成輸出重定向操作。
   剛開始接觸後臺代碼的時候或者說正真接觸一個項目後臺前,看到用vsnprintf()格式化輸出,覺得我靠,寫那麼多我沒見過的函數,最終還是爲了一個目的: printf()來輸出,這不是繞一個圈子然後又回來麼,簡單的在需要日誌輸出的地方直接print就好了,不過現在覺得那麼想是多麼的不小白,每次輸出的日誌都不是單一的,在每個地方都單一的輸出,看到那樣的日誌你會選擇自殺,
還得從va_list,va_start(),va_end()和 ... 說起:
在c++中又函數重載功能,c語言中也是又類似功能的,如經常見到的  int fun(char *format, ... ),該函數的參數個數是未定的,以此實現了類似重載的功能,我們用的最多的printf() 函數就是這樣實現的,現在來講講這個怎麼用:
正如大家知道的那樣,函數傳入的參數是保存在棧中的(可以看看彙編,這個是怎樣實現的),第一個參數在棧的最頂端,最後一個參數在棧的最底端,
對於函數void  fun(char *formt,...);進行調用fun("a","b","c","d","e","f","g");
va_list:複合類型,va_list  args;聲明變量args,可以看作爲一個指針 
va_start(args, formt):將args指向第一個參數"a"
va_arg(args, 參數類型):args指向下一個參數
va_end(args):將args置爲無效
eg:
#include <cstdio>
#include <cstdarg>
#include <iostream>
void fun(int a,...)
{
va_list pp;
int n=1;
va_start(pp,a);
do
{
printf("第 %d 個參數 =%d\n",n++,a);
a=va_arg(pp,int);
}
while (a!=0);
}
int main()
{
fun(20,40,60,80,0);
return 0;
}
結果:
1 個參數 =20
2 個參數 =40
3 個參數 =60
4 個參數 =80
現在開始說vsnprintf():
頭文件:#include <stdarg.h>
函數聲明: int vsnprintf(char* str, size_t size, const char* format, va_list ap);
參數說明:
char *str [out],把生成的格式化的字符串存放在這裏.
size_t size [in], str可接受的最大字節數,防止產生數組越界.
const char *format [in], 指定輸出格式的字符串,它決定了你需要提供的可變參數的類型、個數和順序。
va_list ap [in], va_list變量. va:variable-argument:可變參數
函數功能:將可變參數格式化輸出到一個字符數組。
用法類似於vsprintf,不過加了size的限制,防止了內存溢出(size爲str所指的存儲空間的大小)。
返回值:執行成功,返回寫入到字符數組str中的字符個數(不包含終止符),最大不超過size;執行失敗,返回負值。 
eg:
int WriteErrorLog(const char* pszFmt,...)
{
static char szBuffer[4096];
va_list args;
va_start(args, pszFmt);
int nTmpLen = vsnprintf(szBuffer,4096,pszFmt, args);
va_end(args);
if (nTmpLen < 0)
{
return -1;
}
printf("ID = %d::%s \n",m_p->GetID(),szBuffer);
return 0;
}
這樣你要輸出的串就格式化到szBuffer中了,其實就是類似於自己改寫printf(),使其可以嵌套使用,
這個問題是解決了,但是還有一個新問題就是szBuffer越界了怎麼辦,這裏取的數字4096,如果在大點大到動態分配內存也會越界怎麼辦,
其實也是有辦法解決的,是用一段彙編處理,將在下次筆記中記錄講解












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章