Variable Arguments of Type float Are Promoted to Type double

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