PRB: Unpredictable Results When >1 va_arg() in Parameter List (66738)
The information in this article applies to:
- The C Run-Time (CRT), when used with:
- Microsoft Visual C++ for Windows, 16-bit edition 1.0
- Microsoft Visual C++ for Windows, 16-bit edition 1.5
- Microsoft Visual C++, 32-bit Editions 1.0
- Microsoft Visual C++, 32-bit Editions 2.0
- Microsoft Visual C++, 32-bit Editions 2.1
- Microsoft Visual C++, 32-bit Editions 4.0
- Microsoft Visual C++, 32-bit Editions 5.0
- Microsoft Visual C++, 32-bit Editions 6.0
This article was previously published under Q66738 SYMPTOMS
When the va_arg() macro is used more than once in a function parameter
list, an application produces different results depending on the version of
the C compiler used to build the application.
CAUSE
The C standard does not precisely define expression evaluation order. In
many cases, the compiler implementation determines the order in which an
application evaluates expressions.
RESOLUTION
To preserve the original order of the arguments, use the va_arg() macro
only once in a given expression. One method is to evaluate the expression
in a loop that processes each variable argument and stops when the last
parameter is reached.
MORE INFORMATION
The va_arg() macro provides a method to access the arguments of a function
when the function can accept a variable number of arguments. The macro
returns a variable parameter by incrementing the value of the arg_ptr that
points to the list of arguments. The values returned depend on the order in
which the application evaluates the va_arg() macros.
However, because the C language does not guarantee the order in which most
expressions are evaluated, application code should not depend on a
particular evaluation order. The sample code below demonstrates this
behavior and the unwanted side effects that can occur when code that
depends on evaluation order is compiled with different versions of the same
compiler.
Sample Code #1
#include <stdio.h>
#include <stdarg.h>
void myfunc(int, ...);
void main(void)
{
myfunc(1, 2, 3, 4);
}
void myfunc(int first, ...)
{
va_list arg_ptr;
va_start(arg_ptr, first);
printf("%d %d %d %d\n", first, va_arg(arg_ptr, int),
va_arg(arg_ptr, int),
va_arg(arg_ptr, int));
}
When this sample is compiled with C version 5.1 or C/C++ version 8.0 for MS-
DOS, the sample produces the following output:
1 4 3 2
However, when this sample is compiled with Microsoft C versions 6.0, 6.0a,
6.0ax, Microsoft C/C++ version 7.0, or Microsoft Visual C++ 32-bit Edition,
versions 1.0 through 4.2, the sample produces the following output:
1 4 4 4
In Microsoft Visual C++ versions 5.0 and 6.0, the output is the same as C 5.1 and C/C++ 8.0.
In the following sample code, the expressions are evaluated correctly
without regard to the expression evaluation order.
Sample Code #2
#include <stdio.h>
#include <stdarg.h>
void myfunc(int, ...);
void main(void)
{
myfunc(1, 2, 3, 4, -1); /* -1 is a flag */
}
void myfunc(int first, ...)
{
int temp;
va_list arg_ptr;
va_start(arg_ptr, first);
temp = first;
while(temp != -1) /* test for flag (-1) */
{
printf("%d ", temp);
temp = va_arg(arg_ptr, int);
}
}
The output is as follows:
1 2 3 4
Modification Type: | Minor | Last Reviewed: | 7/5/2005 |
---|
Keywords: | kbCRT kbprb KB66738 |
---|
|