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

Resuelto andrewrk asked hace 16 años • 10 respuestas

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?

andrewrk avatar Aug 13 '08 09:08 andrewrk
Aceptado

Declaración

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

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

Esto indica que el parámetro fserá un puntero a una función que tiene un voidtipo de retorno y que toma un único intparámetro. La siguiente función ( print) es un ejemplo de una función a la que se podría pasar funccomo parámetro porque es del tipo adecuado:

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

Llamada de función

Al llamar 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 func, pasándole la función de impresión.

Cuerpo de función

Al igual que con cualquier parámetro, funcahora puede usar el nombre del parámetro en el cuerpo de la función para acceder al valor del parámetro. Digamos que funcaplicará la función que se pasa a los números 0-4. Consideremos, primero, cómo se vería el bucle al llamar a imprimir directamente:

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

Dado que funcla declaración del parámetro de 's dice que fes el nombre de un puntero a la función deseada, primero recordamos que if fes un puntero, entonces *fes lo que fapunta (es decir, la función printen 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);
  }
}

Fuente

Niyaz avatar Aug 13 '2008 02:08 Niyaz

Esta pregunta ya tiene la respuesta para definir punteros de función, sin embargo, pueden resultar muy complicados, especialmente si los va a pasar por su aplicación. Para evitar este malestar, recomendaría que escribadef el puntero de función en algo más legible. Por ejemplo.

typedef void (*functiontype)();

Declara una función que devuelve nula y no acepta argumentos. Para crear un puntero de función para este tipo, ahora puede hacer:

void dosomething() { }

functiontype func = &dosomething;
func();

Para una función que devuelve un int y toma un carácter, lo harías

typedef int (*functiontype2)(char);

y para usarlo

int dosomethingwithchar(char a) { return 1; }

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

Existen bibliotecas que pueden ayudar a convertir los punteros de función en tipos agradables y legibles. ¡ La biblioteca de funciones de impulso es excelente y vale la pena el esfuerzo!

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

es mucho mejor que el anterior.

roo avatar Aug 13 '2008 02:08 roo

Desde C++ 11, puede utilizar la biblioteca funcional para hacer esto de forma concisa y genérica. La sintaxis es, por ejemplo,

std::function<bool (int)>

¿Dónde boolestá aquí el tipo de retorno 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 utilizar 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);
}
Richard avatar Jul 20 '2015 16:07 Richard

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 el 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();
}
Yogeesh H T avatar Nov 23 '2015 12:11 Yogeesh H T

Las funciones se pueden "pasar" como punteros de función, según ISO C11 6.7.6.3p8: " Una declaración de un parámetro como ''tipo de retorno de función'' se ajustará a ''tipo de retorno de función'' , como en 6.3 .2.1." Por ejemplo, esto:

void foo(int bar(int, int));

es equivalente a esto:

void foo(int (*bar)(int, int));
doppelheathen avatar Nov 27 '2018 15:11 doppelheathen