ID Number: Q71424
5.10 6.00 6.00a | 5.10 6.00 6.00a
MS-DOS | OS/2
Summary:
When passing arguments of type float to a function that accepts a
variable number of arguments, those floats not explicitly declared in
the prototype will be promoted to type double.
In this case, the macros va_start and va_arg will use sizeof(float) to
determine the argument size, when the actual size is sizeof(double).
This will give unexpected results because the values on the stack will
be interpreted incorrectly.
More Information:
The sample program below returns the sum of a variable list of
floating-point values. The sum returned is not correct because the
variables of type float (other than the float that was declared) are
promoted to double, but are treated as floats by va_start and va_arg.
Although this situation causes unintended results, this is expected
behavior that conforms to the ANSI standard. Section 3.3.2.2 of the
ANSI standard states:
If the expression that denotes the called function has a type
that does not include a prototype, the integral promotions are
performed on each argument and arguments that have type float
are promoted to double. These are called the default argument
promotions.
.
.
.
If the expression that denotes the called function has a type
that includes a prototype, the arguments are implicitly
converted to the types of the corresponding parameters. The
ellipsis notation in a function prototype declarator causes
argument type conversion to stop after the last declared
parameter. The default argument promotions are performed on
trailing arguments.
To work around this situation, use doubles instead of floats for
values that will be passed to functions that accept a variable number
of arguments.
Sample Code
-----------
/* Compile options needed: none
*/
#include <stdio.h>
#include <stdarg.h>
float sum( int num, float first, ... );
void main()
{
float total;
total = sum( 3, 11.11F, 22.22F, 33.33F );
printf( "11.11 + 22.22 + 33.33 = %f\n\n", total );
}
float sum( int num, float first, ... )
{
int count;
float sum, temp = first;
va_list marker;
sum = 0.0F;
va_start( marker, first );
for( count=1; count<num; count++ )
{
sum += temp;
temp = va_arg( marker, float );
}
sum += temp;
va_end( marker );
return( sum );
}
Program Output
--------------
11.11 + 22.22 + 33.33 = -321864398408282700000000000.000000