Reputation: 79450
So this simple case just prints out 3
when passing a function:
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_1_fn_a(int fn_x(int, int)) {
return fn_x(1, 2);
}
int
main() {
int x = case_1_fn_a(add);
printf("%d\n", x);
return 0;
}
But now I would like to pass a function to a function. How do I do that?
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_2_fn_a(int fn_x(int, int), int fn_y(int, int)) {
return add(fn_x(add, add), fn_y(add, add));
}
int
case_2_fn_b(int fn_x(int, int)) {
return fn_x(1, 2);
}
int
main() {
int x = case_2_fn_a(case_2_fn_b, case_2_fn_b);
printf("%d\n", x);
return 0;
}
But I get these errors (I get all kinds of different errors if I try adjusting this or that thing, so nothing works):
tmp.c:11:19: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:11:24: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:11:35: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:11:40: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:21:23: warning: incompatible pointer types passing 'int (int (*)(int, int))' to parameter of type 'int (*)(int, int)'
[-Wincompatible-pointer-types]
int x = case_2_fn_a(case_2_fn_b, case_2_fn_b);
^~~~~~~~~~~
tmp.c:10:17: note: passing argument to parameter 'fn_x' here
case_2_fn_a(int fn_x(int, int), int fn_y(int, int)) {
^
tmp.c:21:36: warning: incompatible pointer types passing 'int (int (*)(int, int))' to parameter of type 'int (*)(int, int)'
[-Wincompatible-pointer-types]
int x = case_2_fn_a(case_2_fn_b, case_2_fn_b);
^~~~~~~~~~~
tmp.c:10:37: note: passing argument to parameter 'fn_y' here
case_2_fn_a(int fn_x(int, int), int fn_y(int, int)) {
^
6 warnings generated.
Segmentation fault: 11
Essentially I want to pass a series of functions to function "A", and then have function "A" take those functions (let's call them functions "B", "C", and "D"), and call them with a few functions as parameters. Functions "B", "C" and "D" then take their function arguments, and pass simple values to them like integers or chars.
Upvotes: 3
Views: 81
Reputation: 224892
First, when passing functions as parameters, you typically want to use function pointers instead. So instead of this as a parameter:
int fn_x(int, int)
You would use this:
int (*fn_x)(int, int)
Now for the main problem: functions (and function pointers) as parameters and return values can have confusing syntax. Creating typedefs for function pointers greatly simplifies this.
So let's make the following typedefs:
typedef int (*addfunc)(int, int);
typedef int (*fnb)(addfunc);
typedef int (*fna)(fnb, fnb);
So now you have:
int
case_2_fn_a(fnb fn_x, fnb fn_y) {
return add(fn_x(add), fn_y(add));
}
int
case_2_fn_b(addfunc fn_x) {
return fn_x(1, 2);
}
As you can see, the syntax is much cleaner. It's also more apparent that the body of case_2_fn_a
had a error where fn_x
and fn_y
were being passed two parameters instead of one.
If you really wanted to do this without typedefs, case_2_fn_a
would look like this:
int
case_2_fn_a(int (*fn_x)(int (*)(int,int)), int (*fn_y)(int (*)(int,int))) {
return add(fn_x(add), fn_y(add));
}
Upvotes: 5
Reputation: 1286
As said in the comments, use function pointers:
Case 1:
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_1_fn_a(int(*fn_x)()) {
return (*fn_x)(1, 2);
}
int
main() {
int x = case_1_fn_a(&add);
printf("%d\n", x);
return 0;
}
Case 2:
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_2_fn_a(int (*fn_x)(), int(*fn_y)()) {
return add((*fn_x)(&add), (*fn_y)(&add));
}
int
case_2_fn_b(int(*fn_x)()) {
return (*fn_x)(1, 2);
}
int
main() {
int x = case_2_fn_a(&case_2_fn_b, &case_2_fn_b);
printf("%d\n", x);
return 0;
}
Upvotes: 2