Puntero de función en C

En C, como punteros de datos normales (int *, char *, etc.), podemos tener punteros a funciones. El siguiente es un ejemplo simple que muestra la declaración y la llamada de función usando el puntero de función.

#include <stdio.h>
// A normal function with an int parameter
// and void return type
void fun(int a)
{
    printf("Value of a is %d\n", a);
}
  
int main()
{
    // fun_ptr is a pointer to function fun() 
    void (*fun_ptr)(int) = &fun;
  
    /* The above line is equivalent of following two
       void (*fun_ptr)(int);
       fun_ptr = &fun; 
    */
  
    // Invoking fun() using fun_ptr
    (*fun_ptr)(10);
  
    return 0;
}

Producción:

Value of a is 10

¿Por qué necesitamos un corchete adicional alrededor de los punteros de función como fun_ptr en el ejemplo anterior?
Si quitamos el corchete, entonces la expresión «void (*fun_ptr)(int)» se convierte en «void *fun_ptr(int)», que es la declaración de una función que devuelve un puntero vacío. Vea la siguiente publicación para más detalles.
¿Cómo declarar un puntero a una función?

Los siguientes son algunos datos interesantes sobre los punteros de función.

 
1) A diferencia de los punteros normales, un puntero de función apunta al código, no a los datos. Normalmente, un puntero de función almacena el inicio del código ejecutable.

2) A diferencia de los punteros normales, no asignamos memoria de desasignación usando punteros de función.

 
3) El nombre de una función también se puede usar para obtener la dirección de las funciones. Por ejemplo, en el siguiente programa, hemos eliminado el operador de dirección ‘&’ en la asignación. También hemos cambiado la llamada de función eliminando *, el programa aún funciona.

#include <stdio.h>
// A normal function with an int parameter
// and void return type
void fun(int a)
{
    printf("Value of a is %d\n", a);
}
  
int main()
{ 
    void (*fun_ptr)(int) = fun;  // & removed
  
    fun_ptr(10);  // * removed
  
    return 0;
}

Producción:

Value of a is 10

 
4) Al igual que los punteros normales, podemos tener una array de punteros de función. El siguiente ejemplo en el punto 5 muestra la sintaxis para una array de punteros.

 
5) El puntero de función se puede utilizar en lugar de la caja del interruptor. Por ejemplo, en el siguiente programa, se le pide al usuario que elija entre 0 y 2 para realizar diferentes tareas.

#include <stdio.h>
void add(int a, int b)
{
    printf("Addition is %d\n", a+b);
}
void subtract(int a, int b)
{
    printf("Subtraction is %d\n", a-b);
}
void multiply(int a, int b)
{
    printf("Multiplication is %d\n", a*b);
}
  
int main()
{
    // fun_ptr_arr is an array of function pointers
    void (*fun_ptr_arr[])(int, int) = {add, subtract, multiply};
    unsigned int ch, a = 15, b = 10;
  
    printf("Enter Choice: 0 for add, 1 for subtract and 2 "
            "for multiply\n");
    scanf("%d", &ch);
  
    if (ch > 2) return 0;
  
    (*fun_ptr_arr[ch])(a, b);
  
    return 0;
}
Enter Choice: 0 for add, 1 for subtract and 2 for multiply
2
Multiplication is 150 

 
6) Al igual que los punteros de datos normales, un puntero de función se puede pasar como argumento y también se puede devolver desde una función.
Por ejemplo, considere el siguiente programa en C donde wrapper() recibe un void fun() como parámetro y llama a la función pasada.

// A simple C program to show function pointers as parameter
#include <stdio.h>
  
// Two simple functions
void fun1() { printf("Fun1\n"); }
void fun2() { printf("Fun2\n"); }
  
// A function that receives a simple function
// as parameter and calls the function
void wrapper(void (*fun)())
{
    fun();
}
  
int main()
{
    wrapper(fun1);
    wrapper(fun2);
    return 0;
}

Este punto en particular es muy útil en C. En C, podemos usar punteros de función para evitar la redundancia de código. Por ejemplo , se puede usar una función qsort() simple para clasificar arrays en orden ascendente o descendente o en cualquier otro orden en el caso de una array de estructuras. No solo esto, con punteros de función y punteros vacíos, es posible usar qsort para cualquier tipo de datos.

// An example for qsort and comparator
#include <stdio.h>
#include <stdlib.h>
  
// A sample comparator function that is used
// for sorting an integer array in ascending order.
// To sort any array for any other data type and/or
// criteria, all we need to do is write more compare
// functions.  And we can use the same qsort()
int compare (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}
  
int main ()
{
  int arr[] = {10, 5, 15, 12, 90, 80};
  int n = sizeof(arr)/sizeof(arr[0]), i;
  
  qsort (arr, n, sizeof(int), compare);
  
  for (i=0; i<n; i++)
     printf ("%d ", arr[i]);
  return 0;
}

Producción:

5 10 12 15 80 90

Similar a qsort(), podemos escribir nuestras propias funciones que se pueden usar para cualquier tipo de datos y pueden realizar diferentes tareas sin redundancia de código. A continuación se muestra una función de búsqueda de ejemplo que se puede utilizar para cualquier tipo de datos. De hecho, podemos usar esta función de búsqueda para encontrar elementos cercanos (por debajo de un umbral) escribiendo una función de comparación personalizada.

#include <stdio.h>
#include <stdbool.h>
  
// A compare function that is used for searching an integer
// array
bool compare (const void * a, const void * b)
{
  return ( *(int*)a == *(int*)b );
}
  
// General purpose search() function that can be used
// for searching an element *x in an array arr[] of
// arr_size. Note that void pointers are used so that
// the function can be called by passing a pointer of
// any type.  ele_size is size of an array element
int search(void *arr, int arr_size, int ele_size, void *x,
           bool compare (const void * , const void *))
{
    // Since char takes one byte, we can use char pointer
    // for any type/ To get pointer arithmetic correct,
    // we need to multiply index with size of an array
    // element ele_size
    char *ptr = (char *)arr;
  
    int i;
    for (i=0; i<arr_size; i++)
        if (compare(ptr + i*ele_size, x))
           return i;
  
    // If element not found
    return -1;
}
  
int main()
{
    int arr[] = {2, 5, 7, 90, 70};
    int n = sizeof(arr)/sizeof(arr[0]);
    int x = 7;
    printf ("Returned index is %d ", search(arr, n,
                               sizeof(int), &x, compare));
    return 0;
}

Producción:

Returned index is 2

La función de búsqueda anterior se puede utilizar para cualquier tipo de datos escribiendo una comparación personalizada separada().

 
7) Muchas funciones orientadas a objetos en C++ se implementan utilizando punteros de función en C. Por ejemplo , funciones virtuales . Los métodos de clase son otro ejemplo implementado usando punteros de función. Consulte este libro para obtener más detalles.

Artículo relacionado: Punteros en C y C++ | Conjunto 1 (Introducción, Aritmética y Array)

Referencias:
http://www.cs.cmu.edu/~ab/15-123S11/AnnotatedNotes/Lecture14.pdf

http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-087-practical-programming-in-c-january-iap-2010/lecture-notes/MIT6_087IAP10_lec08.pdf

http://www.cs.cmu.edu/~guna/15-123S11/Lectures/Lecture14.pdf

Este artículo es una contribución de Abhay Rathi . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *