Click to See Complete Forum and Search --> : Help with stdarg.h.


SRcoder!
March 23rd, 2004, 11:05 AM
Picked up Programming Windows 5th Edition by Charles Petzold and had a problem understanding some of the code in the second chapter. A friend of mine tried to explain it to me, and I thought I had it untill I tried writting my own program and it came out incorrectly. Here is the code, it should produce an output of 1, yet it produces an output of a very large negative number.


#include <stdarg.h>
#include <iostream>

int minus(int iVariable, int iOne, ... );

int main(void)
{
int iReturn=minus(5, 1, 1, 2);
std::cout<<"The value is: "<<iReturn<<std::endl;
return(0);
}

int minus(int iVariable, int iOne, ...)
{
int iInc(iOne);
va_list id1;
va_start(id1, iOne);
while(iInc!=-1)
{
iVariable-=iInc;
iInc=va_arg(id1, int);
}
va_end(id1);
return(iVariable);
}

Paul McKenzie
March 23rd, 2004, 12:00 PM
Your call must have the last argument of -1 so as to terminate the loop:

int iReturn=minus(5, 1, 1, 2, -1);
//...
while(iInc!=-1) // <-- Look at this line in your function

Regards,

Paul McKenzie

lavut
March 23rd, 2004, 03:13 PM
the normal function call looks like this in assembly if you try to compile the source with option /Fa

push 2
push 1
push 1
push 5
push return address
and the stack will looks like this:


id1 -8
iInc -4 <-----var declared inside funct
ebx 0<---base address
return address +4
5 +8
1 +12 <------id1
1 +16
2 +18

So when you call va_start(id1, iOne), it will fetch the stack address of iOne which is at +12 relative to the base address 0.
Each time you call va_arg(id1, int), id1 is incremented by sizeof (int) which will return the value after iOne in the function parameter list, until it reach the final parameter which is 2 in your example code.But the loop will never stop until it find a value -1 in way down the stack . So that's why you have to put a -1 in your parameter list as Paul suggested so you can exit the loop with the result expected.

hopes this clears up a bit

or you can look inside stdarg.h for the nittygritty details of vastart and va_arg

SRcoder!
March 23rd, 2004, 06:33 PM
Ohh, ok. Thanks I get it, but is there a way to not have to add it. For example have it look for next untill it does not exist? I just compiled the code replacing:


while(iInc!=-1)


with:


while(iInc)


It doesn't look as if it worked. I got a result of a large negative number again using that method. Ohh well. I guess I will just have to remember to terminate the arguments with -1 or what ever I happen to use in my while statement. Thanks, that works perfectly.

Paul McKenzie
March 23rd, 2004, 07:17 PM
Originally posted by SRcoder!
Ohh, ok. Thanks I get it, but is there a way to not have to add it?No. That's how variable argument functions work -- you're responsible to come up with the "stopping" criteria, it isn't automatic. In your case, it was the -1 argument. For a function such as printf( ), the stopping criteria is when the end of the format string is reached by the internal printf() parser.

Regards,

Paul McKenzie