Reputation:
#include <stdarg.h>
#include <stdio.h>
void varfun(int n,...){
va_list ptr;
int num;
va_start(ptr,n);
num=va_arg(ptr,int);
printf("\n%d",num);
}
int main(int argc, char **argv){
varfun(3,7.5,-11.2,0.66);
return 0;
}
Look at the above code, i expect the output to be the first variable parameter value casted to int i.e 7.5 casted to int, i.e. 7. But the output is 0. What is wrong in this?
Upvotes: 2
Views: 6577
Reputation: 75095
This is not really casting but merely "reading the first few bytes" (*) of a floating point variable and considering it an integer.
You need to read this argument as its actual type, a double, and then casting as an int.
num = (int) va_arg(ptr, double);
(*) Technically, the behavior associated with va_arg(ptr, wrong_type) is undefined
. "reading the first few bytes" is a figure of speech, only describing what typically may happen. No serious program should rely on such implementation details.
Upvotes: 1
Reputation: 1260
It won't automatically cast the value 7.5 into an int
like that. You'll need to use va_arg
to retrieve the value as a double
and then do the cast afterwards.
va_arg(ptr,int)
is actually expecting the value stored at ptr
to be a bitwise representation of an int
, and it's not.
Upvotes: 0
Reputation: 263177
Your second argument, 7.5
is of type double
, but your call va_arg(ptr, int)
is treating it as an int. This means undefined behavior.
A variadic function has to be able to figure out the number and type(s) of the arguments -- and if the caller lies, you're out of luck. printf
-like functions do this via the format string; other functions might treat all their arguments as pointers and use a trailing null pointer as a sentinel.
Upvotes: 3
Reputation: 108968
The va_arg
does not convert the argument. It interprets it as the indicated type. And if the types don't match, you invoke Undefined Behaviour.
va_arg(ptr, int); /* take the next 4 bytes from the stack and interpret them as an `int` */
va_arg(ptr, double); /* take the next 8(?) bytes ... and interpret as double */
(int)va_arg(ptr, double); /* ... convert to int */
Also note the cast isn't really needed in your snippet. The compiler will convert automatically
void varfun(int n, ...) {
va_list ptr;
int num;
va_start(ptr, n);
num = va_arg(ptr, double); /* interpret as double, then convert to int */
printf("%d\n",num);
}
Upvotes: 8