va_list c ++有问题

时间:2016-04-07 14:04:25

标签: c++ arguments variable-assignment variadic-functions

我只是想用一个可变数量的参数编写一个非常简单的函数,这样我就可以编写一个类似于printf的函数来进行赋值。查看va_list的文档后,我不确定为什么此代码会一直给我运行时错误:

enter image description here

这是我的代码:

void print(string sOne , ...);
void main()
{
    print("first string", "second string", "third String");
    system("pause");
}

void print(string sOne , ...)
{
    va_list arguments;
    va_start(arguments, sOne);
     while ((va_arg(arguments, int)) != 0)
    {
        string printString = va_arg(arguments, string);
        cout << printString;
    }
    va_end(arguments);
}

3 个答案:

答案 0 :(得分:6)

您对可变参数函数的实现非常不正确。

首先,您需要一种方法来告诉函数有多少参数或它们何时结束。标准printf通过使用格式说明符(它们的数字表示args的数量)来完成此操作,另一个选项是显式提供数字。你似乎期望最后一个参数是整数0(奇怪的选择btw。),但你永远不会将0作为最后一个参数传递给你的可变函数。

其次,您无法从可变参数函数参数中移植std::string。完全支持普通类型,对于字符串,您必须使用char*std::string并不简单,因为它具有非平凡的构造函数和析构函数。有些编译器支持非平凡类型作为此类函数的参数,但其他编译器不支持,因此您不应该尝试这样做。

最后但并非最不重要:变量函数在C ++世界中没有地位,即使是作业也是如此。

答案 1 :(得分:2)

SergeyA解释了为什么你的代码不起作用,这是可能的解决方案之一:

void print(const char *sOne , ...);
int main()
{
    print("first string", "second string", "third String", nullptr);
    system("pause");
}

void print(const char *sOne , ...)
{
    va_list arguments;
    va_start(arguments, sOne);
    while (sOne)
    {
        cout << sOne;
        sOne = va_arg(arguments, const char *);
    }
    va_end(arguments);
}

再次举例说明如果你必须使用C风格的可变参数函数,你应该考虑使用C ++ variadic模板。

答案 2 :(得分:0)

因此,您的实施存在一些问题。

  1. 您没有通过va_arg的来电次数限制,并且:
  2.   

    如果va_arg中没有更多参数,或者ap(促销后)中的下一个参数的类型与{{1}不兼容,则调用ap ,行为未定义

    1. 您似乎想要打印&#34;第一个字符串&#34;因此,您需要将其作为T的一部分传递,您可以使用计数作为第一个参数来清理 1 2 :{{1 }}
    2. 您正在将va_list作为参数传递给void print(int sOne, ...),并希望将其推广到const char*va_list不会为您宣传。它会将您传入的任何内容转换为string中指定的类型如果您尝试将va_list视为va_arg,则最终会出现运行时错误,如您所见。 可以使用const char*作为string参数进行更正:string this is only conditionally supported in C++ 您需要使用{{1} }
    3. 您正在呼叫va_list以推进"first string"s "second string"s, "third String"s循环。你需要使用一个计数器。调用va_arg(arguments, const char*)提取下一个参数,如果参数可用,他们测试。而是使用您在 2 va_arg
    4. 中传入的计数

      进行这些更改应该让您的代码看起来像这样:

      for

      Live Example