Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic function (va_arg) doesn't work with float?

Tags:

I have a variadic function which takes a float parameter. Why doesn't it work?

va_arg(arg, float) 
like image 872
Eric des Courtis Avatar asked Jun 30 '12 00:06

Eric des Courtis


People also ask

What does Va_arg function do?

The va_arg() macro retrieves a value of the given var_type from the location given by arg_ptr and increases arg_ptr to point to the next argument in the list. The va_arg() macro can retrieve arguments from the list any number of times within the function.

How do you access Variadic arguments?

To access variadic arguments, we must include the <stdarg. h> header.

Is printf variadic function?

Variadic functions are functions (e.g. printf) which take a variable number of arguments.


2 Answers

Parameters of functions that correspond to ... are promoted before passing to your variadic function. char and short are promoted to int, float is promoted to double, etc.

6.5.2.2.7 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.

The reason for this is that early versions of C did not have function prototypes; parameter types were declared at the function site but were not known at the call site. But different types are represented differently, and the representation of the passed argument must match the called function's expectation. So that char and short values could be passed to functions with int parameters, or float values could be passed to functions with double parameters, the compiler "promoted" the smaller types to be of the larger type. This behavior is still seen when the type of the parameter is not known at the call site -- namely, for variadic functions or functions declared without a prototype (e.g., int foo();).

like image 153
Sergey Kalinichenko Avatar answered Sep 18 '22 06:09

Sergey Kalinichenko


As @dasblinkenlight has mentioned, float is promoted to double. It works fine for me:

#include <stdio.h>           #include <stdarg.h>  void foo(int n, ...) {        va_list vl;     va_start(vl, n);      int c;      double val;       for(c = 0; c < n; c++) {         val = va_arg(vl, double);         printf("%f\n", val);     }      va_end(vl); }   int main(void) {   foo(2, 3.3f, 4.4f);   return 0; } 

Output:

3.300000 4.400000 
like image 21
Jack Avatar answered Sep 21 '22 06:09

Jack