Is it possible pass a function as a parameter in C? [duplicate] - c

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
How do you pass a function as a parameter in C?
Is it possible pass a function as a parameter in C? If yes, how?

No, you can't pass a 'function' as a parameter. You can, however, pass a pointer to a function instead.
When you reference a function by name without the parentheses for a function invocation, you are referencing a pointer to a function. Thus, for example, we could consider a function that generates a table of values for a mathematical function:
#include <math.h>
#include <stdio.h>
static void generator(double lo, double hi, double inc, double (*function)(double))
{
double x;
for (x = lo; x < hi; x += inc)
printf("x = %6g; f(x) = %6g\n", x, (*function)(x))
}
int main(void)
{
generator(0.0, 1.0, 0.02, sin);
generator(0.0, 1.0, 0.02, cos);
generator(0.0, 1.0, 0.02, sqrt);
return(0);
}
Here, the functions 'sin()', 'cos()', and 'sqrt()' all have the same prototype schema: function taking a double argument and returning a double value. Note that if I mistakenly wrote:
generator(0.0, 1.0, 0.02, sin());
I would get a bunch of compilation errors - one because 'sin()' expects an argument, and another because 'generator()' expects a pointer to a function and not a double value as the last argument.
(Also note that a good program would at least identify the function it is calculating, and the repeated increments of a double number is not a good idea for accuracy. It is but an example.)

Use a pointer to function.
Like int (*ptr2_fun)()
Receiving function being:
int execute_your_function(int (*fun)())
Here you have some examples

Use function pointers

Yes. Not a function per se but a pointer to a function instead.
See qsort().
int cmp(const void *a, const void *b) { /* ... */ }
/* ... */
qsort(data, nelems, sizeof *data, cmp); /* pass the function `cmp` to qsort() */

Great function pointer tutorial here:
http://www.newty.de/fpt/index.html

Sure, you can use a function pointer.
#include <stdio.h>
typedef void (*bar_callback)(void);
void foo(void)
{
puts("foo");
}
void bar(bar_callback callback)
{
puts("bar");
callback();
}
int main(int argc,char **argv)
{
bar(foo);
return 0;
}

Related

Which type to use for an arbitrary function pointer in C?

In short, my question is: does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
It is common to define call-back function types with a void * parameter to pass on an arbitrary data package whose format is known to the call-back function, but not to the caller.
For example:
typedef void (* EventFunctionType)(void *data);
void RegisterEventFunction(EventFunctionType function, void *data);
An "EventFunction" can then be registered with a data pointer which will be passed to the function when it is called.
Now suppose we want to pass a function pointer to the call-back. The function could have any prototype which would be known to the specific call-back function, just like the arbitrary data structure above.
A void * cannot hold a function pointer, so which type could be used?
Note: An obvious solution to this problem would be to wrap the function pointer in a data structure with the correct function pointer type, but the question is if the function pointer could be passed on directly in a generic form which the call-back could then cast to a pointer with the correct prototype?
There are no function pointer type that works the same as/similar to to void-pointer.
But function pointers has another characteristic that can be used. It's already referenced in the answer linked in this question:
In the C11 draft standard N1570, 6.3.2.3 ยง8:
A pointer to a function of one type may be converted to a pointer to a function of another type and back again.
This mean that you can use any function pointer type as your "arbitrary function pointer type". It doesn't matter as long as you know how to get back to the real/original type (i.e. know the original type so that you can cast correctly).
For instance:
typedef void (*func_ptr_void)(void);
and then use func_ptr_void as your "arbitrary function pointer type".
But notice that unlike conversion between void* and other object pointer types, the conversion between function pointers will always require an explicit cast. The code example below shows this difference:
#include <stdio.h>
typedef void (*func_ptr_void)(void);
typedef int (*f_int)(int);
int bar(int n)
{
return n * n;
}
int test(func_ptr_void f, int y)
{
f_int fc = (f_int)f; // Explicit cast
return fc(y);
}
int foo(void* p)
{
int* pi = p; // Explicit cast not needed
return *pi;
}
int main(void)
{
int x = 42;
void* pv = &x; // Explicit cast not needed
printf("%d \n", foo(pv));
func_ptr_void fpv = (func_ptr_void)bar; // Explicit cast
printf("%d \n", test(fpv, 5));
return 0;
}
does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
No. Two function pointers are only compatible if their return types and parameters (including qualifiers) match.
However, pointer conversions between any two function pointers by means of a cast are well-defined (6.3.2.3/8) as long as you don't invoke the function through the wrong pointer type. This means that you can use any function pointer type as a "generic function pointer" as long as you keep track of what function that pointer actually points at. Such as using an extra enum for that purpose.
Generally when using function pointers, we don't do that however, but instead define a common interface. For example like the callbacks to bsearch/qsort which use the form int (*)(const void*, const void*).
Here's an example of "keep track of type using enum", which is not something I particularly recommend but otherwise perfectly well-defined:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
typedef enum
{
INTFUNC,
DOUBLEFUNC
} functype_t;
typedef void generic_func_t (void);
typedef int int_func_t (int);
typedef int double_func_t (double);
typedef struct
{
generic_func_t* fptr;
functype_t type;
} func_t;
void func_call (const func_t* f)
{
switch(f->type)
{
case INTFUNC: ((int_func_t*)f->fptr ) (1); break;
case DOUBLEFUNC: ((double_func_t*)f->fptr) (1.0); break;
}
}
int main (void)
{
func_t f1 = { (generic_func_t*)intfunc, INTFUNC };
func_t f2 = { (generic_func_t*)doublefunc, DOUBLEFUNC };
func_call(&f1);
func_call(&f2);
}
That's "old school" C, but it is not recommended since it is clunky, brittle and not really type safe. In modern C programming we wouldn't write that kind of code however, but replace that whole mess with something like this:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
#define func_call(obj) \
_Generic((obj), \
int: intfunc, \
double: doublefunc) (obj) \
int main (void)
{
func_call(1);
func_call(1.0);
}

How can I pass the following argument and what kind is it?

I am relatively new in C and found the code of this question. How do you pass the argument double (*f)(double) of the function and how does the pointer works out in this?
Here's the function:
double derivative(double (*f)(double), double x0, int order)
My guess was that first you need something like:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
double f(double x){
return pow(x,2);
}
int main(){
double x = 2;
int order = 2;
derivative(f(x), x , 2);
}
I tried it but it didn't work. Thanks for the help.
double (*f)(double) is a function pointer. It means you need to pass a pointer to (or just the name of) a function. In your attempt, you're calling the function, then passing the return value, which isn't correct.
The correct way would be:
derivative(f, x, 2);

How do I call this function with the arguments (void (*store) (int*,int))?

I'm new to c and not really familiar with pointers or how this method is setup to be called in main with these arguments. I have a bit of an understanding of pointer snow, but i'm still confused with one being in the method arguments. Do I pass in a pointer and an int? Do I need to pass in anything at all? Do I even need the main method or can I just run the program with is_little_endian as my main method?
#include "test_endian.h"
#include <stdio.h>
int is_little_endian(void (*store)(int*,int)) {
int x;
unsigned char *byte_ptr = (unsigned char*)(&x);
store(&x, 1);
printf("the address for x is %u\n", *byte_ptr);
return 0;
}
int main() {
}
Function is_little_endian accepts only one parameter which is neseccary.
This parameter is a pointer to a function, which accepts pointer to int, then int and returns nothing (void). You just need to pass there a pointer to some function, like that:
void example(int * a, int b) { }
int main() {
is_little_endian(example);
}
Or any other function you wish. You can read more about pointers to function there: How do function pointers in C work?
And yes, you need the main method to run the program, like your body needs your heart. ;)

Is it possible to write a function which returns a pointer to a function different from the function in its argument?

I have recently stumbled on this curious thought while handling a C code.
I have written a function which returns a double and takes in as argument the pointer to a function and a certain number of parameters, namely
double template_1(double (*)(double),...);
this function correctly identifies a certain property of a real function
double f(double );
represented as a pointer in template_1, in order to maketemplate_1 valid for every real function I might plug-in.
Now I had to write another function, let it be:
double derivative(double (*)(double),double);
double derivative(double (*f)(double),double x){
double epsilon = ...;
return ( f(x+epsilon)-f(x-epsilon) )/(2.0*epsilon);
}
again with f in the argument to make it work for every f.
My question is: since I would like to use derivative in template_1 without modifying it, is it possible to write a function which takes derivative and spits out something that has the form of double (*)(double ) ?
My idea was to define typedef double (*real_function)(double);
and then to define
real_function g(double (*derivative)(double (*)(double),double ) )
which I'd like it to spit out something like: double derivative_2(double x); so that I could define something like g(derivative) = double (*h)( double); directly in template_1 argument
unfortunately I don't have the faintest idea of how to make this work, or even if it can work.
There are a couple ways to do anonymous functions in C. As the comments said, they aren't portable. But depending on the use case you may find this useful: Anonymous functions using GCC statement expressions
A couple of people have seemed to have similar issues, not sure how portable they are but they may be resourceful:
https://github.com/graphitemaster/lambdapp
https://github.com/Leushenko/C99-Lambda
Basically, if there's a way to architect your program in a way that doesn't require anonymous functions, then do it that way. If you have no other option, then I would give one of these a shot.
Warning: I am a C++ developer with little C knowledge so everything that follows is likely unidiomatic C.
As KerrekSB said, you would need to carry some state with your function. This is not possible with raw functions but you can define a struct that carries the state and add a function that works with this struct. This obviously has the drawback of losing the nice function call syntax. I whipped up an example:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
typedef double (*raw_fptr)(double);
struct real_function;
typedef double (*evaluate_function)(struct real_function*, double);
struct real_function {
evaluate_function evaluate;
};
typedef struct real_function real_function;
double evaluate(real_function *f, double x) {
if(f) {
return f->evaluate(f, x);
}
return NAN;
}
struct raw_real_function {
real_function real_function_base;
raw_fptr raw_function;
};
typedef struct raw_real_function raw_real_function;
double evaluate_raw_real_function(real_function *f_base, double x) {
if(f_base) {
raw_real_function *f = (raw_real_function*)f_base;
return f->raw_function(x);
}
return NAN;
}
raw_real_function make_raw_real_function(raw_fptr function) {
raw_real_function result;
result.raw_function = function;
result.real_function_base.evaluate = evaluate_raw_real_function;
return result;
}
struct derive_real_function {
real_function real_function_base;
real_function *function_to_derive;
};
typedef struct derive_real_function derive_real_function;
double derive(real_function *f_base, double x) {
derive_real_function *f = (derive_real_function*)f_base;
double epsilon = 1e-3;
double upper = evaluate(f->function_to_derive, x+epsilon);
double lower = evaluate(f->function_to_derive, x-epsilon);
double result = (upper - lower)/(2.0*epsilon);
return result;
}
derive_real_function make_derivative(real_function * function_to_derive) {
derive_real_function result;
result.real_function_base.evaluate = derive;
result.function_to_derive = function_to_derive;
return result;
}
double x_cubed(double x) {
return x * x * x;
}
int main(int argc, char **argv) {
raw_real_function x_cubed_wrapped = make_raw_real_function(x_cubed);
derive_real_function derived = make_derivative(&x_cubed_wrapped.real_function_base);
derive_real_function derived_twice = make_derivative(&derived.real_function_base);
double x = atof(argv[1]);
double derivative = evaluate(&derived.real_function_base, x);
double second_derivative = evaluate(&derived_twice.real_function_base, x);
printf("derivative of x^3 at %f = %f\n", x, derivative);
printf("second derivative of x^3 at %f = %f\n", x, second_derivative);
return 0;
}
See (a slight variaton, due to input limitations) running here.
How does it work? I faked some inheritance with the structs real_function, raw_real_function and derive_real_function to generate virtual function calls. The struct real_function serves as the container of a virtual function table consisting of only the entry evaluate. This function pointer points to the "derived" structs' relevant evaluate function:
raw_real_function instances point to evaluate_raw_real_function (as initialized in make_raw_real_function. derive_real_function instances point evaluate to derive (as initialized in make_derivative).
When calling evaluate on the real_function_base member, it will call the associated evaluation function, which casts the real_function* to it's associated struct pointer and does what is needed with that information.
Since everything is just a real_function*, we can chain them at will but need to convert "normal" functions into the real_function format, that's what make_raw_real_function does.
If you have a function my_fancy_function:
double my_fancy_function (double x) { return sin(x) + cos(x); }
Then, you can use a helper macro that creates the derived function for you.
#define DEFINE_DERIVATIVE_OF(FUNC) \
double derivative_of_ ## FUNC (double x) { \
return derivative(FUNC, x); \
}
DEFINE_DERIVATIVE_OF(my_fancy_function)
You then pass this newly defined function to your template.
template_1(derivative_of_my_fancy_function, x, y, z);

c standard library sort function from programming pearls

#include <algorithm>
#include <stdio.h>
#include <iostream>
int intcomp(int *x,int *y) { return *x-*y;};
int a[10000];
int main(void){
int i; int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
qsort(a,n,sizeof(int),intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
it is just copy of code i have two question it show me that intcomp is incompatible in this code
and also what does intcomp function?
and also what is in windows 7 EOF? how tell program that it reached EOF?
the qsort() function requires a pointer with a particular signature.
Your function has the wrong signature so it is complaining.
Your function has the signature:
int intcomp(int *x,int *y)
While qsort requires the signature:
int intcomp(void const* xp,void const* yp)
Please note the difference in the parameter types.
A corrected version of the function is:
int intcomp(void const* xp,void const* yp)
{
// Modified for C as the tag on the question changed:
// int x = *static_cast<int const*>(xp);
// int y = *static_cast<int const*>(yp);
int x = *((int const*)(xp));
int y = *((int const*)(yp));
return x-y;
}
The function qsort() is passed a function pointer as the third parameter.
This function pointer (in your case intcomp()) is used to compare values in the array passed. Each call provides pointers into the array. The result of the function should be:
Less than 0: if x is smaller than y
0: If x is equal to y
Greater than 0: If x is larger than y
First of all: the question is labeled C++ and you #include <algorithm> and <iostream>, but your code is 100% C.
Martin York already gave the answer how to correct the signature of the function you pass to qsort().
However, the "true"(TM) C++ solution would be to use std::sort<> instead of qsort!
#include <algorithm>
#include <stdio.h>
bool intcomp(int a, int b) { return a<b; }
int a[10000];
int main(void){
int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
std::sort(&a[0], &a[n], intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
Note that incomp() takes ints and not int pointers, and returns a bool. Just like operator<() would.
Also note that in this case, you could forget the intcomp and just use std::sort(&a[0], &a[n]), which will use std::less<>, which will use operator<(int, int).
intcomp is an "Int Compare" function. It is passed a pointer to 2 ints and returns 0 if they are the same, a positive value is x > y and a negative value is x < y.
qsort is passed a pointer to this function and calls it each time it wants to know how to sort a pair of values.
The docs for qsort should give you some more details.
eg http://www.cppreference.com/wiki/c/other/qsort
qsort is in stdlib.h, so include that file at the beginning. Note that algorithm and iostream aren't needed.
#include <stdlib.h>
As Martin York mentioned, qsort needs a function which it will use to compare the values:
void qsort( void *buf, size_t num, size_t size, int (*compare)(const void*, const void *) );
Here is a good example on how to use qsort: http://www.cppreference.com/wiki/c/other/qsort
Edit: Ri was faster....

Resources