The title says it all. Can function be passed as argument in variadic function and if so, how can I access it?
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
void func(double x, int n, ...){
va_list fs;
va_start(fs, n);
for (int i = 0; i < n; i++)
{
va_arg(fs, *); //this is where I get confused
}
}
int main(){
double x = 60.0 * M_PI / 180.0;
func(x, 3, &cos, &sin, &exp);
}
The second argument to va_args is the type to convert to. In this case each function has compatible types, specifically they take a single double as an argument and return a double. The type of a pointer to such a function is double (*)(double), so that it what you would use for the type.
double (*f)(double) = va_arg(fs, double (*)(double));
double result = f(x);
Also, don't forget to call va_end(fs); after the loop.
Related
I am learning how to use functions passing through pointers.
I have a function that chops a double d into two parts, the whole_part and the fraction_part. So “425.25” would be chopped into “425” and “.25”.
I'm getting errors related to passing through pointer types. I'm not sure where problems like this arise. Any help would be appreciated!
#include <math.h>
#include <stdio.h>
#include <limits.h>
void chop(double, long *, double *);
int main(void)
{
double d;
long * whole_part;
double * fraction_part;
printf("enter a double ");
scanf("%lf", &d);
// Call the function
chop(d, &whole_part, &fraction_part);
printf("%.10lf chopped is %ln and %.10lf", d, whole_part, fraction_part);
return 0;
}
void chop(double d, long *whole_part, double *fraction_part)
{
*whole_part = (int)d;
*fraction_part = d - (double)whole_part;
}
Initial problems:
long whole_part and double fraction_part should not be initialized in main as their variable pointers.
The function chop() should call the pointer to whole_part when attempting to use it to determine fraction_part.
#include <stdio.h>
#include <limits.h>
void chop(double, long *, double *);
int main(void)
{
double d;
long whole_part;
double fraction_part;
printf("enter a double ");
scanf("%lf", &d);
// Call the function
chop(d, &whole_part, &fraction_part);
printf("%.10lg chopped is %li and %.10lg\n", d, whole_part, fraction_part);
return 0;
}
void chop(double d, long *whole_part, double *fraction_part)
{
*whole_part = (int)d;
*fraction_part = d - (double)*whole_part;
}
Here's my code :
#include <stdio.h>
#include <stdlib.h>
void *create_array(int size) {
double *v;
v = (double*)malloc(size * sizeof(double));
v[0] = (double)size;
return (void*)v;
}
int main() {
void *a;
double b = 5;
a = create_array(10);
a[1] = b;
return 0;
}
I'm trying to assign the value stored in b to (*a[1]). I get the following error :
"main.c:19:9: error: incomplete type 'void' is not assignable
a[1]=b;"
~~~~^
Main Answer
void is an incomplete type and cannot be used in expressions, including assignments. You can, however, have pointers to this type, void *. void * is a type that means “this points to something, but we are not saying what at this point.”
In order to use a void *, you must say what it points to, by converting it to a different kind of pointer, such as double *, which says “this points to a double.”
C, unlike C++, will do this conversion automatically in assignments. If we declare a with double *a; and then we assign it with a = create_array(10);, then the void * that is returned from create_array is automatically converted to a double * for storing in a. After that, we can write a[1] = b; to store b in the double at a[1].
Supplement
Your create_array contains a mix of double * and void *. It is better to either write a routine that is designed for a specific type:
double *create_array(int NumberOfElements)
{
double *v = malloc(NumberOfElements * sizeof *v);
v[0] = NumberOfElements; // (Yuck, this is ugly.)
return v;
}
or to write a routine that handles any type:
void *create_array(int NumberOfElements, size_t SizeOfElement)
{
void *v = malloc(NumberOfElements * SizeOfElement);
// Cannot store size easily since we do not know what element type is.
return v;
}
As noted, that business about storing the number of elements in the first element is messy. It is better to handle the size separately, even if that requires writing more code.
Also, avoid calling something just a “size,” because this can be confusing: Is the size of an array the number of elements in it or the number of bytes? The name or accompanying comments should always make the unit of measurement clear.
neither pointers nor variables can be void type, just function's return
change to:
#include <stdio.h>
#include <stdlib.h>
double *create_array(int size){
double *v;
v=(double*)malloc(size*sizeof(double));
v[0]=(double)size;
return (double*)v;
}
int main() {
double *a;
double b;
b=5;
a=create_array(10);
a[1]=b;
return 0;
}
You can't dereference a void *, but you can use a cast:
#include <stdio.h>
#include <stdlib.h>
void *
create_array(int size)
{
double *v = malloc(size * sizeof *v);
if( v == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
v[0] = (double)size;
return v;
}
int
main(void)
{
void *a;
double b = 5.0;
double *c;
c = a = create_array(10);
((double *)a)[1] = b;
printf("%f %f\n", c[0], c[1]);
return 0;
}
The second piece of code is not giving the correct value as it only passes the value of r from what I see. However, I would like to make this code work without using return (just for learning how to do it in this other way). Also, what is considered best practice between these two options? Thank you! :-)
#include <stdio.h>
#define PI 3.1416
float area(float r);
int main(void)
{
float r = 10;
printf("Area: %.2f", area(r));
return 0;
}
float area(float r) {
return PI * r * r;
}
#include <stdio.h>
#define PI 3.1416
float area(float r);
int main(void)
{
float r = 10;
printf("Area: %.2f", area(r));
return 0;
}
float area(float r) {
PI * r * r;
}
I would like to make this code work without using return (just for learning how to do it in this other way).
Using return is the only way to actually return a value from a function.
However, the C syntax provides two alternative options:
It is possible to pass another pointer as argument to the function, which points to an object in the caller, in which you then assign the value of the expression.
For example:
#include <stdio.h>
#define PI 3.1416
void area(float r, float *p);
int main(void)
{
float r = 10;
float s;
area(r, &s);
printf("Area: %.2f", s);
return 0;
}
void area(float r, float* p) {
*p = PI * r * r;
return;
}
It is also possible to define a global object and assign the value of the expression to that global object instead.
For example:
#include <stdio.h>
#define PI 3.1416
float s;
void area(float r);
int main(void)
{
float r = 10;
area(r);
printf("Area: %.2f", s);
return 0;
}
void area(float r) {
s = PI * r * r;
return;
}
But that is considered to be bad practice because the connections from and to the function and with that the actual use of the function are then much harder to understand than using parameters and return types, which on the other hand show the relation and the use of the particular function call pretty good.
The use of global objects shall be avoided if possible although there are cases where a global objects is suitable, if you f.e. use an object in multiple functions and the role of the object is exactly defined. But in the provided example of yours, a global object does not fit very well and shall be avoided.
If no value shall be returned, define the return type of the function as of type void.
This is my first time working with pointers to function.
What I'm trying to do is create a function called essay, that gets a pointer to another function , an integer num, and then num doubles.
The function essay, will multiply the arguments, and then return the value of the function i recieved as an argument, with the product.
This sounds complex but it really is quite simple.
Example:
essay(sin,2,pi,1/2) will return the value of sin(pi/2)
this is my code...for some reason it doesnt let me send the pointer to the function sin. Says no instance of overloaded function sin matches argument list, but this is exactly how i saw my teacher do it...I think.
#include <stdio.h>
#include <conio.h>
#include <stdarg.h>
#include <math.h>
double (*pfunc)(double);
double essay(double* pfunc(double),double num, ... )
{
int i;
double product=1,result;
va_list arguments;
va_start(arguments,num);
for(i=0;i<num;i++)
product*=va_arg(arguments,double);
va_end(arguments);
result=*(pfunc(product));
return result;
}
void main()
{
double x,y;
x=3.14159265358979323846;
y=0.5;
printf("%lf",essay(sin,2,x,y));
getch();
}
this is wrong
double essay(double* pfunc(double),double num, ... )
Here you're passing a function as a parameter which return a pointer to double, that not make sense, should be:
double essay(double (*pfunc)(double),double num, ... )
Here you're passing a pointer to a function which returns a double and receive a double as a parameter
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
// removed extra var
double essay(double (*pfunc)(double), double num, ...) // added parens
{
int i;
double product = 1, result;
va_list arguments;
va_start(arguments, num);
for (i = 0; i < num; i++)
product *= va_arg(arguments, double);
va_end(arguments);
result = pfunc(product); // removed extra parens
return result;
}
void main()
{
double x, y;
x = 3.14159265358979323846;
y = 0.5;
printf("%lf", essay(sin, 2, x, y));
}
This is what I'd do, assuming a C99 compiler that accepts variable declarations in for loops and at arbitrary points in a block of code. Note the use of the typedef for the function pointer type (MathFunc2 would be for a function that takes two arguments, etc), and the use of int (rather than double) for the number of values in the argument list.
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
typedef double (*MathFunc1)(double);
static double essay(MathFunc1 function, int num, ...)
{
double product = 1.0;
va_list arguments;
va_start(arguments, num);
for (int i = 0; i < num; i++)
product *= va_arg(arguments, double);
va_end(arguments);
double result = (*function)(product);
return result;
}
int main(void)
{
double x = 3.14159265358979323846; // M_PI?
double y = 0.5;
printf("%f\n", essay(sin, 2, x, y));
}
Can we pass variable number of arguments to a function in c?
Here is an example:
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
int main(void){
f();
exit(EXIT SUCCESS);
}
int maxof(int n_args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n_args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n", maxof(3, i, j[42], 0));
}
If it is a function that accepts a variable number of arguments, yes.
Yes, if the function accepts variable arguments. If you need to make your own variable-argument function, there are macros that begin with va_ which give you access to the arguments.
make sure that the variable argument list should always be at the end of the argument list
example: void func(float a, int b, ...) is correct
but void func(float a, ..., int b) is not valid
"You should consider that using variadic functions (C-style) is a dangerous flaw," says Stephane Rolland. You can find his helpful post here.