2012-04-16 21 views
0

設置我有一個實用C函數正常工作不工作:vsprintf_s()va_list的時候已經長由局部變量

void UtilDisplayMessage(char* strCaption, char* strMessageFormat, int iArgCount, ...) 
{ 
    // Initialize the variable arg list 
    va_list lstArgs; 
    va_start(lstArgs, iArgCount); 

    // Format the message 
    vsprintf_s(g_strMessage, UTIL_DEF_MESSAGE_SIZE, strMessageFormat, lstArgs); 

    // Destroy the variable arg list 
    va_end(lstArgs); 

    // Use formatted string here... 
} 

但我想刪除「iArgCount」參數,所以我做了測試功能,看起來像這樣:

void UtilDisplayMessageEasy(char* strCaption, char* strMessageFormat, ...) 
{ 
    // Initialize the variable arg list 
    va_list lstArgs; 

    int iParamCount = 1; 
    va_start(lstArgs, iParamCount); 

    // Format the message 
    vsprintf_s(g_strMessage, UTIL_DEF_MESSAGE_SIZE, strMessageFormat, lstArgs); 

    // Destroy the variable arg list 
    va_end(lstArgs); 

    // Use formatted string here... 
} 

,但我得到虛假的結果,如果我在一個整數值,通過這個電話:

UtilDisplayMessageEasy("TEST", "The value is %i.", 1); 

我得到一個訪問衝突異常時,我通過在這個調用的字符串:

UtilDisplayMessageEasy("TEST", "This is only a %s.", "TEST"); 

但是,如果我把我原來的功能,像這樣它工作正常:

UtilDisplayMessage("TEST", "This is only a %s.", 1, "TEST"); 

是否真的有我是否將參數或本地參數傳遞到va_start()中有這樣的根本區別?

另外我知道,變量參數不是很安全,應謹慎使用,但肯定這種無害的東西不應該設置報警聲。

非常感謝您對此問題的任何意見。

+0

在'UtilDisplayMessageEasy'將'va_start(lstArgs,iParamCount);'改爲'va_start(lstArgs,strMessageFormat);' – 2012-04-16 20:15:35

+0

啊!而已!非常感謝你! – BlazeCell 2012-04-16 21:39:46

回答

1

va_start的第二個參數需要是函數聲明中的...之前的最後一個參數。所以在第一種情況下需要爲iArgCount,在第二種情況下需要爲strMessageFormat。在第二個參數中使用其他任何東西(例如局部變量)會給你一個未定義的行爲 - 希望編譯器會給你一個錯誤,但它可能只是默默地接受它並隨意做一些事情。

+0

哇!你認爲我會在文檔中看到這一點。非常感謝! – BlazeCell 2012-04-16 21:29:41

0

va_list變量被用來從它剛好在它之前的參數中派生出...的起始地址。這是一個要求。 你不能使用本地,你可能想要做

va_start(lstArgs, strMessageFormat); 

改爲。

+0

非常感謝! – BlazeCell 2012-04-16 21:30:22