Punteros a funciones

En C, los punteros a funciones se utilizan como cualquier otro tipo de punteros; pueden ser pasados como argumentos de otras funciones, usados en arreglos, retornados por funciones, etc. La única diferencia es que lo que se encuentra al tomar el contenido de (operador *) estos punteros, no es un dato sino un pedazo de código ejecutable.

Al igual que en los arreglos estáticos, el nombre de una función que ya existe puede ser utilizada donde se requiera un puntero a función. .

Su utilización permite implementar funcines genéricas que operen sobre otras funciones ( búsqueda de ceros, integración, etc).

Declaración

Para declarar un puntero a una función se utiliza la siguiente sintaxis:


tipo_de_retorno (* nombre_de_puntero) (tipo1 arg1, tipo2 arg2, ...);

Los nombres de los argumentos (arg1, arg2, etc) no son necesarios, pero pueden servir para entender cómo se usa la función. Ejemplo:


double (* f) (double x);  /* declara el puntero a función f notar que los parentesis son necesarios para distinguir de (double *) f(double) */

f = sin;  /* lo inicializa con la direccion de memoria de una función double->double */
x = f(3.14); /* utiliza el puntero como si fuera una función */
x = (* f)(3.14); /* derreferencia explicitamente el puntero al utilizarlo */

Las dos últimas sentencias son equivalentes ( de la misma manera que cuando trabajabamos con punteros a arreglos, era indistinto decir p[i] o *(p+i)), la primera forma es más comoda, pero la segunda muestra explicitamente que p es un puntero.

Como argumentos de funciones

Si recordamos que la lista de argumentos de una función es también la declaración de cada uno de ellos, podemos comprender que la sintaxis sea: tipo_retorno nombre_funcion ( ..., tipo_retorno (*nombre_puntero)(tipo1 arg1, ...), ...,);

En el prototipo no es necesario poner el nombre del puntero, ni tampoco el nombre de los argumentos.

Ejemplo:

ejem_puntfunc1.c
#include <stdio.h>
#include <math.h>

double suma_cuadrados(double (*)(double), int, int);
double inversa ( double x) { return 1.0/x; }

int main()
{
  double s;
  s = suma_cuadrados(sin, 1, 100);
  printf("suma de 1 a 100 de sin(i)^2 = %lf\n", s);
  s = suma_cuadrados(inversa,1,  100);
  printf("suma de 1 a 100 de sin(i)^2 = %lf\n", s);
  return 0;
}

double suma_cuadrados ( double (*f)(double x), int i0, int if )
{
	double s = 0,x;
	int i;
	for (i=i0; i<=if; i++)
   {
       x = i;
       s += f(x)*f(x); /* (*f)(x)*(*f)(x) en forma más explícita */
   }
   return s;
}

Arreglos de Punteros a función

Para declarar un arreglo de punteros a función la sintaxis es:

  tipo_de_retorno (* nombre_de_puntero[tamaño]) (tipo1 arg1, tipo2 arg2, ...);

Por ejemplo:


double (* f[3]) (double);
f[0] = sin;
f[1] = inversa;
f[2] = cos;
 
x = f[0](3.14); /* x = sin(3.14) */
x = f[1](3.14); /* x = ivnersa(3.14) */
x = f[2](3.14); /* x = cos(3.14) */

En el ejemplo anterior podríamos haber utilizado un arreglo de punteros, de la siguiente manera: [an error occurred while processing this directive]


ICOM