#include<stdio.h>
#include<ctype.h>
#include<math.h>
#include<malloc.h>
#include<stdarg.h>

/* Source: Variable Argument Functions, codeproject.com */
float add(float x, ...) 
 {
    va_list arg_values;
    float item, sum = 0.0;
    
    va_start(arg_values,x);
    
    while(1)
    { 
    
    /* Different type conversions are applied to functions with variable arguments than to usual functions. Variable promotions: float is promoted to type double. 
       Any char, short, enumerated type, and bit field is promoted to signed or unsigned int. */
        item=va_arg(arg_values,double);//correct
        //item=(float)va_arg(arg_values,double);//correct
        //item=va_arg(arg_values,float); 
        /* Incorect as size of float and double is different. Compiler assumes double, but you are specifying float. 
        When it will increment arg_values to point to next argument by adding the size of float, it will be pointing to wrong data. */
    
        if(item == 0.0)
            break;
       
        sum += item;
     }
     va_end(arg_values); 
     return(sum);
  }

int main()
{
    float y=20;
    double z=30;
    int x=5;
    printf("%f\n", add(20, 6.0, 5.0, 10.0, 0.0));
    printf("%f\n", add(30, 5.0, 5.0, y, z, 0.0));

return(0);
}

/* va_start is a macro which initializes the va_list by adding the size of the argument v (which is the last fixed argument) to the 
address of v. So it now points to the first unknown argument. 
#define va_start(ap,v)(ap=(va_list)&v+_INTSIZEOF(v))
*/