0

我有一个可以正常工作的实用程序 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() 真的有这么根本的区别吗?

另外我知道可变参数不是很安全,应该小心使用,但这种无害的东西肯定不应该让警报响起。

感谢您对此问题的任何意见。

4

2 回答 2

1

va_list 变量用于从它之前的参数导出 ... 的起始地址。这是一个要求。你不能使用本地的,你可能想做

va_start(lstArgs, strMessageFormat);

反而。

于 2012-04-16T21:00:52.627 回答
1

的第二个参数va_start需要是...函数声明中的最后一个参数。所以它需要iArgCount在第一种情况和strMessageFormat第二种情况下。在第二个参数中使用其他任何东西(例如局部变量)会给您带来未定义的行为——希望编译器会给您一个错误,但它可能只是默默地接受它并做一些随机的事情。

于 2012-04-16T20:39:33.557 回答