¿Cómo se pasa una función como parámetro en C?


Quiero crear una función que realice una función pasada por parámetro en un conjunto de datos. ¿Cómo se pasa una función como parámetro en C?

Author: gsamaras, 2008-08-13

5 answers

Declaración

Un prototipo para una función que toma un parámetro de función se parece a lo siguiente:

void func ( void (*f)(int) );

Esto indica que el parámetro f será un puntero a una función que tiene un tipo de retorno void y que toma un único parámetro int. La siguiente función (print) es un ejemplo de una función que podría pasarse a func como parámetro porque es el tipo apropiado:

void print ( int x ) {
  printf("%d\n", x);
}

Llamada a la función

Cuando llamando a una función con un parámetro de función, el valor pasado debe ser un puntero a una función. Utilice el nombre de la función (sin paréntesis) para esto:

func(print);

Llamaría a func, pasándole la función print.

Cuerpo de la función

Como con cualquier parámetro, func ahora puede usar el nombre del parámetro en el cuerpo de la función para acceder al valor del parámetro. Digamos que func aplicará la función que se pasa a los números 0-4. Considere, en primer lugar, lo que el loop parecería llamar a print directamente:

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

Dado que la declaración de parámetros de func dice que f es el nombre de un puntero a la función deseada, recordamos primero que si f es un puntero, entonces *f es la cosa a la que f apunta (es decir, la función print en este caso). Como resultado, simplemente reemplace cada aparición de print en el bucle anterior con *f:

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

De http://math.hws.edu/bridgeman/courses/331/f05/handouts/c-c++-notes.html

 619
Author: Niyaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-24 01:59:51

Esta pregunta ya tiene la respuesta para definir punteros de función, sin embargo, pueden ser muy desordenados, especialmente si va a pasarlos alrededor de su aplicación. Para evitar este inconveniente, le recomendaría que escriba el puntero de la función en algo más legible. Por ejemplo.

typedef void (*functiontype)();

Declara una función que devuelve void y no toma argumentos. Para crear un puntero de función a este tipo ahora puede hacer:

void dosomething() { }

functiontype func = &dosomething;
func();

Para una función que devuelve un int y toma un char que haría

typedef int (*functiontype2)(char);

Y usarlo

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

Hay bibliotecas que pueden ayudar a convertir los punteros de función en tipos legibles. La biblioteca boost function es genial y vale la pena el esfuerzo!

boost::function<int (char a)> functiontype2;

Es mucho más agradable que el anterior.

 106
Author: roo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 13:22:06

Desde C++11 puede usar la biblioteca funcional para hacer esto de una manera sucinta y genérica. La sintaxis es, por ejemplo,

std::function<bool (int)>

Donde bool es el tipo de retorno aquí de una función de un argumento cuyo primer argumento es de tipo int.

He incluido un programa de ejemplo a continuación:

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

A veces, sin embargo, es más conveniente usar una función de plantilla:

// 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);
}
 45
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-11 14:02:36

Pase la dirección de una función como parámetro a otra función como se muestra a continuación

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

También podemos pasar la función como parámetro usando puntero de función

#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();
}
 9
Author: Yogeesh H T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-23 13:20:07

Necesita pasar un puntero de función . La sintaxis es un poco engorrosa, pero es realmente poderosa una vez que te familiarizas con ella.

 2
Author: saint_groceon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-13 02:18:28