Reputation: 27
I'm just trying to write a very simple function with a variable number of arguments so I can write a function similar to printf for an assignment. After looking at the documentation for va_list
I'm not sure why this code keeps giving me run-time errors:
Here is my code:
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);
}
Upvotes: 0
Views: 6034
Reputation: 44268
SergeyA explained why your code does not work, here is one of the possible solutions:
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);
}
Again this example is in case you have to use C-style variadic function, you should consider using C++ variadic template instead.
Upvotes: 2
Reputation: 62613
Your implementation of variadic function is very incorrect.
First, you need a some way to tell the function how many arguments there are or when they end. Standard printf
does this by using format specifiers (their number represents the number of args), another option is to provide the number explicitly. You seem to expect the last argument to be integer 0 (strange choice btw.), but you never pass 0
as a last argument to your variadic function.
Second, you can't portably extract std::string
from variadic function arguments. Only trivial types are fully supported, and for strings you have to use char*
. std::string
is not trivial, because it has non-trivial constructor and destructor. Some compilers do support non-trivial types as arguments for such functions, but others do not, so you shouldn't try this.
The last, but not the least: variadic functions have no place in C++ world, even for assignments.
Upvotes: 7
Reputation: 38959
So you have several problems with your implementation.
va_arg
and:If
va_arg
is called when there are no more arguments inap
, or if the type of the next argument inap
(after promotions) is not compatible withT
, the behavior is undefined
va_list
, you can clean up both 1 and 2 by using a count as your first argument: void print(int sOne, ...)
const char*
s as arguments to your va_list
and expecting it to promote those to string
s. va_list
will not promote for you. It casts whatever you passed in to the type specified in va_arg
And if you try to treat a const char*
as a string
you will end up with a run-time error, as you have seen. string
s as your va_list
arguments: "first string"s "second string"s, "third String"s
this is only conditionally supported in C++va_arg(arguments, const char*)
va_arg
to advance your for
loop. You'll need to use a counter for that. Calls to va_arg
extract the next argument, they do not test if an argument is available. Instead use your count that you passed in as part of 2 for (auto i = 0; i < sOne; ++i)
Making those changes should get your code looking something like this:
void print(int sOne, ...) {
va_list arguments;
va_start(arguments, sOne);
for (auto i = 0; i < sOne; ++i) {
cout << va_arg(arguments, const char*) << endl;
}
va_end(arguments);
}
Upvotes: 0