我有一个正常工作的实用程序C函数:
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 :(得分:1)
va_start
的第二个参数需要是函数声明中...
之前的最后一个参数。因此,在第一种情况下需要iArgCount
,在第二种情况下需要strMessageFormat
。在第二个参数中使用其他任何东西(例如局部变量)会给你未定义的行为 - 希望编译器会给你一个错误,但它可能只是默默地接受它并做一些随机的事情。
答案 1 :(得分:1)
va_list变量用于从它之前的参数派生...的起始地址。这是一项要求。 你不能使用本地,你可能想做
va_start(lstArgs, strMessageFormat);
代替。