How do you pass a function as a parameter in C?

717,905

Solution 1

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);
  }
}

Source

Solution 2

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.

Solution 3

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);
}

Solution 4

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();
}

Solution 5

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));
Share:
717,905
andrewrk
Author by

andrewrk

open source software developer

Updated on September 24, 2021

Comments

  • andrewrk
    andrewrk over 2 years

    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?

    • Mooing Duck
      Mooing Duck over 10 years
      If you're using functions/arrays as variables, ALWAYS use typedef.
    • AminM
      AminM about 10 years
      We call it Function pointer
    • mckenzm
      mckenzm almost 9 years
      The function name should be a ponter to the function. Most people learning C cover qsort sooner or later which does exactly this ?
    • andrewrk
      andrewrk over 8 years
      @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.
    • Mooing Duck
      Mooing Duck over 8 years
      @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
      Mooing Duck over 8 years
      Oh, I just noticed the comment says "arrays as variables". Yes, that's misworded. I meant array pointers as variables.
    • Jan Hus
      Jan Hus about 4 years
      The function passed as parameter can also have parameter(s) .Could somebody show me an example HOW to access those function parameter(s) ? ?
    • Bob Jarvis - Слава Україні
      Bob Jarvis - Слава Україні about 3 years
      See the standard library functions qsort and bsearch for examples of how this is done.
    • Tasos Papastylianou
      Tasos Papastylianou over 2 years
      @MooingDuck not disagreeing with either of you, but the upside to me is that you know exactly what's going on at a glance, rather than relying on the programmer having chosen a reasonable name like "funcA", and having to scroll through code files twice to figure out what that variable is for. Having said that, if you have good coding style I can see it working nicely. But then again, if you have good coding style, I can see the explicit version not being a problem either. I have a feeling your style of writing the explicit version above was somewhat intentionally 'dense' to make your point. :)
  • Gauthier
    Gauthier about 12 years
    In 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
    Gauthier about 12 years
    See [c99, 6.9.1§14] for examples. Both are correct of course, I just wanted to mention the alternative.
  • Seng Cheong
    Seng Cheong over 9 years
    Really? The top-rated answer doesn't make a single reference to using a typedef for function pointers? Sorry, have to down-vote.
  • Abhinav Gauniyal
    Abhinav Gauniyal about 9 years
    @JonathonReinhart , what would be advantages with 'typedef' apprach? This version looks much cleaner though and lacks extra statements too. pretty much starter here.
  • Super Cat
    Super Cat over 8 years
    The question is about C; C++ does not apply here.
  • M.M
    M.M over 8 years
    @JonathonReinhart well spotted; it should be explicitly noted that pointer typedefs obfuscate the code and therefore should not be used.
  • Seng Cheong
    Seng Cheong over 8 years
    @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).
  • M.M
    M.M over 8 years
    @JonathonReinhart in that case I would typedef the function type.
  • Seng Cheong
    Seng Cheong over 8 years
    @M.M Is that standard C? I've played with it before, but thought it was a GNU extension.
  • M.M
    M.M over 8 years
    @JonathonReinhart Yes, it was in ANSI C
  • Seng Cheong
    Seng Cheong over 8 years
    Looking at (stackoverflow.com/questions/4574985/…), 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.
  • azmath
    azmath about 8 years
    What if you want to pass a function pointer that returns a pointer as an argument. I tried this:
  • mr_T
    mr_T about 8 years
    The question for C++ (stackoverflow.com/questions/6339970/…) is referred to here, so I think this answer is in place.
  • wizzwizz4
    wizzwizz4 about 8 years
    If 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.
  • lorro
    lorro almost 8 years
    Is there anything against function references, so that we don't have somewhat complex syntax? Last time I've checked, these worked perfectly..
  • Michael Fulton
    Michael Fulton about 6 years
    Maybe the question for C++ shouldn't be referred to here because this question for is C.
  • ufoxDan
    ufoxDan over 4 years
    This question came up first when I searched "c++ function call as parameter", so this answer is serving its purpose well here regardless.
  • Tejas Pendse
    Tejas Pendse over 4 years
    You're just invoking a function. How would you pass some other function in place of IncMultInt?
  • Rafael Eyng
    Rafael Eyng over 4 years
    Very 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
    Rafael Eyng over 4 years
    What document are you quoting from? Any link to it?
  • doppelheathen
    doppelheathen over 4 years
    I'm quoting from the ISO C11 standard.
  • M.Ionut
    M.Ionut about 4 years
    @Gauthier is the asterisk not compulsory because of implicit dereferencing ?
  • Gauthier
    Gauthier about 4 years
    @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.
  • Gennaro Arguzzi
    Gennaro Arguzzi almost 4 years
    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?
  • 12431234123412341234123
    12431234123412341234123 over 3 years
    Isn't boost library C++? Why do you mention it in a C question?
  • Ove
    Ove about 3 years
    @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.
  • Sekomer
    Sekomer almost 3 years
    Correct me if I'm wrong, AFAIK function names are pointers just like array names so in the first example you are passing function object and compiler does implicit conversion, in the second example you are directly passing function pointer which is explicit conversion.
  • Dwedit
    Dwedit over 2 years
    For functions that use a different calling convention, place the calling convention before the first *. Like this: typedef void(__stdcall* funcPtr)(int arg1, int arg2);
  • joanis
    joanis over 2 years
    This might be a good solution, but it found itself in the Low Quality Answers queue for review. Please add some discussion explaining the solution and how it works, to make it more helpful to future readers of this site.
  • Celuk
    Celuk over 2 years
    Here with func(print); we can't pass x parameter to the print function. As in your example, the x parameter is given in the func function by ctr variable. So, is there a way to do passing a value to a function passed as parameter like func(print(5)); ?