I want to create a function that performs a function passed by parameter on a set of data. How do you pass a function as a parameter in C?
-
14If you're using functions/arrays as variables, ALWAYS use `typedef`. – Mooing Duck Jan 13 '14 at 21:09
-
5We call it [Function pointer](http://en.wikipedia.org/wiki/Function_pointer#Example_in_C) – AminM Apr 01 '14 at 11:11
-
The function name should be a ponter to the function. Most people learning C cover qsort sooner or later which does exactly this ? – mckenzm Jul 03 '15 at 02:09
-
6@MooingDuck I don't agree with your suggestion, and your suggestion lacks reasoning to support the conclusion. I personally prefer *never* using typedef on function pointers, and I think it makes the code clearer and easier to read. – andrewrk Dec 16 '15 at 22:26
-
2@andrewrk: You prefer `void funcA(void(*funcB)(int))` and `void (*funcA())()` to `typedef void funcB(); void funcA(funcB)` and `funcB funcA()`? I dont see the upside. – Mooing Duck Dec 16 '15 at 23:27
-
Oh, I just noticed the comment says "arrays as variables". Yes, that's misworded. I meant array pointers as variables. – Mooing Duck Dec 16 '15 at 23:28
-
The function passed as parameter can also have parameter(s) .Could somebody show me an example HOW to access those function parameter(s) ? ? – Jan Hus Apr 18 '20 at 20:34
-
See the standard library functions `qsort` and `bsearch` for examples of how this is done. – Bob Jarvis - Reinstate Monica Feb 15 '21 at 12:45
8 Answers
Declaration
A prototype for a function which takes a function parameter looks like the following:
void func ( void (*f)(int) );
This states that the parameter f
will be a pointer to a function which has a void
return type and which takes a single int
parameter. The following function (print
) is an example of a function which could be passed to func
as a parameter because it is the proper type:
void print ( int x ) {
printf("%d\n", x);
}
Function Call
When calling a function with a function parameter, the value passed must be a pointer to a function. Use the function's name (without parentheses) for this:
func(print);
would call func
, passing the print function to it.
Function Body
As with any parameter, func
can now use the parameter's name in the function body to access the value of the parameter. Let's say that func
will apply the function it is passed to the numbers 0-4. Consider, first, what the loop would look like to call print directly:
for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
print(ctr);
}
Since func
's parameter declaration says that f
is the name for a pointer to the desired function, we recall first that if f
is a pointer then *f
is the thing that f
points to (i.e. the function print
in this case). As a result, just replace every occurrence of print in the loop above with *f
:
void func ( void (*f)(int) ) {
for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
(*f)(ctr);
}
}
-
47In your first and last code examples, the * is not compulsory. Both the function parameter definition and the `f` function call can take `f` just as is without *. It might be a good idea to do it as you do though, to make it obvious that parameter f is a function pointer. But it hurts readability quite often. – Gauthier Feb 22 '12 at 12:52
-
5See [c99, 6.9.1§14] for examples. Both are correct of course, I just wanted to mention the alternative. – Gauthier Feb 22 '12 at 12:58
-
7Really? The top-rated answer doesn't make a single reference to using a `typedef` for function pointers? Sorry, have to down-vote. – Jonathon Reinhart Oct 01 '14 at 08:03
-
4@JonathonReinhart , what would be advantages with 'typedef' apprach? This version looks much cleaner though and lacks extra statements too. pretty much starter here. – Abhinav Gauniyal Feb 22 '15 at 07:04
-
6@JonathonReinhart well spotted; it should be explicitly noted that pointer typedefs obfuscate the code and therefore should not be used. – M.M Nov 24 '15 at 02:39
-
@M.M Disagree. Consider a callback-based API, where callbacks are registered and stored in a context structure. If you use a typedef for the function pointers and want to change their prototype, you only have to change the function pointer typedef, instead of changing it everywhere. This, coming from a guy who disagrees with over-typedefing (namely on structs). – Jonathon Reinhart Nov 24 '15 at 02:58
-
-
@M.M Is that standard C? I've played with it before, but thought it was a GNU extension. – Jonathon Reinhart Nov 24 '15 at 03:02
-
-
Looking at (http://stackoverflow.com/questions/4574985/typedef-a-functions-prototype), the only difference is the inclusion of the `*` when declaring a function pointer, correct? Because you can't define a function from a function typedef. There is a lot of information about typedef-ing function pointers, but not function types. – Jonathon Reinhart Nov 24 '15 at 03:05
-
What if you want to pass a function pointer that returns a pointer as an argument. I tried this: – azmath Mar 10 '16 at 10:01
-
Is there anything against function references, so that we don't have somewhat complex syntax? Last time I've checked, these worked perfectly.. – lorro Jul 26 '16 at 09:29
-
@Gauthier is the asterisk not compulsory because of implicit dereferencing ? – M.Ionut Mar 14 '20 at 09:55
-
@M.Ioan I'm not sure about implementation details, but I usually think of the function identifier to be a pointer to memory (to the start of the function). Consider the following parens pair (empty or not) as an operator that means "run the code at the location pointed to by the preceding identifier". I'm not sure how function pointers are usually implemented, but if functions actually are pointers, I'd be surprised if a function pointer was a pointer to such a pointer, rather than exactly the same. – Gauthier Mar 14 '20 at 10:18
-
Can someone tell me what is the meaning of the parentheses (*f) in void func( void (*f)(int) ) please? Why if i remove them, the code doesn't work? – Gennaro Arguzzi May 28 '20 at 09:03
-
@GennaroArguzzi Precedence. Without the parentheses, the * binds to the void instead of to f, meaning you're declaring f as a function that returns a pointer to void, instead of as a pointer to a function that returns void. – Ove Feb 27 '21 at 21:48
This question already has the answer for defining function pointers, however they can get very messy, especially if you are going to be passing them around your application. To avoid this unpleasantness I would recommend that you typedef the function pointer into something more readable. For example.
typedef void (*functiontype)();
Declares a function that returns void and takes no arguments. To create a function pointer to this type you can now do:
void dosomething() { }
functiontype func = &dosomething;
func();
For a function that returns an int and takes a char you would do
typedef int (*functiontype2)(char);
and to use it
int dosomethingwithchar(char a) { return 1; }
functiontype2 func2 = &dosomethingwithchar
int result = func2('a');
There are libraries that can help with turning function pointers into nice readable types. The boost function library is great and is well worth the effort!
boost::function<int (char a)> functiontype2;
is so much nicer than the above.
![](../../users/profiles/716.webp)
- 6,461
- 8
- 36
- 45
-
4If you want to "turn a function pointer into a type", you don't need the boost library. Just use `typedef`; it's simpler and doesn't require any extra libraries. – wizzwizz4 Apr 09 '16 at 11:50
-
2Isn't boost library C++? Why do you mention it in a C question? – 12431234123412341234123 Oct 02 '20 at 12:48
Since C++11 you can use the functional library to do this in a succinct and generic fashion. The syntax is, e.g.,
std::function<bool (int)>
where bool
is the return type here of a one-argument function whose first argument is of type int
.
I have included an example program below:
// g++ test.cpp --std=c++11
#include <functional>
double Combiner(double a, double b, std::function<double (double,double)> func){
return func(a,b);
}
double Add(double a, double b){
return a+b;
}
double Mult(double a, double b){
return a*b;
}
int main(){
Combiner(12,13,Add);
Combiner(12,13,Mult);
}
Sometimes, though, it is more convenient to use a template function:
// g++ test.cpp --std=c++11
template<class T>
double Combiner(double a, double b, T func){
return func(a,b);
}
double Add(double a, double b){
return a+b;
}
double Mult(double a, double b){
return a*b;
}
int main(){
Combiner(12,13,Add);
Combiner(12,13,Mult);
}
![](../../users/profiles/752843.webp)
- 44,865
- 24
- 144
- 216
-
54
-
17The question for C++ (http://stackoverflow.com/questions/6339970/c-using-function-as-parameter) is referred to here, so I think this answer is in place. – mr_T Mar 24 '16 at 11:00
-
10Maybe the question for C++ shouldn't be referred to here because this question for is C. – Michael Fulton Apr 19 '18 at 16:22
-
13This question came up first when I searched "c++ function call as parameter", so this answer is serving its purpose well here regardless. – ufoxDan Nov 07 '19 at 21:50
Pass address of a function as parameter to another function as shown below
#include <stdio.h>
void print();
void execute(void());
int main()
{
execute(print); // sends address of print
return 0;
}
void print()
{
printf("Hello!");
}
void execute(void f()) // receive address of print
{
f();
}
Also we can pass function as parameter using function pointer
#include <stdio.h>
void print();
void execute(void (*f)());
int main()
{
execute(&print); // sends address of print
return 0;
}
void print()
{
printf("Hello!");
}
void execute(void (*f)()) // receive address of print
{
f();
}
![](../../users/profiles/3725702.webp)
- 2,093
- 18
- 17
-
1Very nice answer, with whole blocks of code (instead of slicing everything into a incomprehensible mess). Could you elaborate on the differences of both techniques? – Rafael Eyng Jan 29 '20 at 15:17
Functions can be "passed" as function pointers, as per ISO C11 6.7.6.3p8: "A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer to function returning type’’, as in 6.3.2.1. ". For example, this:
void foo(int bar(int, int));
is equivalent to this:
void foo(int (*bar)(int, int));
![](../../users/profiles/4206613.webp)
- 298
- 4
- 8
You need to pass a function pointer. The syntax is a little cumbersome, but it's really powerful once you get familiar with it.
![](../../users/profiles/59.webp)
- 5,877
- 5
- 29
- 26
I am gonna explain with a simple example code which takes a compare
function as parameter to another sorting
function.
Lets say I have a bubble sort function that takes a custom compare function and uses it instead of a fixed if statement.
Compare Function
bool compare(int a, int b) {
return a > b;
}
Now , the Bubble sort that takes another function as its parameter to perform comparison
Bubble sort function
void bubble_sort(int arr[], int n, bool (&cmp)(int a, int b)) {
for (int i = 0;i < n - 1;i++) {
for (int j = 0;j < (n - 1 - i);j++) {
if (cmp(arr[j], arr[j + 1])) {
swap(arr[j], arr[j + 1]);
}
}
}
}
Finally , the main
which calls the Bubble sort function by passing the boolean compare function as argument.
int main()
{
int i, n = 10, key = 11;
int arr[10] = { 20, 22, 18, 8, 12, 3, 6, 12, 11, 15 };
bubble_sort(arr, n, compare);
cout<<"Sorted Order"<<endl;
for (int i = 0;i < n;i++) {
cout << arr[i] << " ";
}
}
Output:
Sorted Order
3 6 8 11 12 12 15 18 20 22
![](../../users/profiles/11534375.webp)
- 411
- 3
- 9
It's not really a function, but it is an localised piece of code. Of course it doesn't pass the code just the result. It won't work if passed to an event dispatcher to be run at a later time (as the result is calculated now and not when the event occurs). But it does localise your code into one place if that is all you are trying to do.
#include <stdio.h>
int IncMultInt(int a, int b)
{
a++;
return a * b;
}
int main(int argc, char *argv[])
{
int a = 5;
int b = 7;
printf("%d * %d = %d\n", a, b, IncMultInt(a, b));
b = 9;
// Create some local code with it's own local variable
printf("%d * %d = %d\n", a, b, ( { int _a = a+1; _a * b; } ) );
return 0;
}
![](../../users/profiles/7270598.webp)
- 149
- 1
- 11
-
You're just invoking a function. How would you pass some other function in place of `IncMultInt`? – Tejas Pendse Nov 28 '19 at 05:27