Lección 6 · 6 de 20
Punteros a funciones y callbacks · C
Guarde funciones en variables y arrays con punteros a funciones en C y páselas como callbacks: reglas de precios aplicadas por pasos.

Una función también tiene una dirección, y un puntero a función la guarda. La sintaxis es enrevesada, así que se le pone nombre con typedef: typedef double (*PriceRule)(double); define PriceRule como «puntero a una función que recibe un double y devuelve un double». add_vat, discount y round_up encajan en ese tipo.
apply_all recibe una de esas funciones en el parámetro rule y la llama con rule(prices[i]) para cada precio. Es un callback: apply_all sabe recorrer el array, pero lo que se hace con cada precio lo decide quien la llama.
Al pasar una función basta su nombre, sin paréntesis: discount es la dirección de la función; discount(5) sería llamarla.
steps es un array de structs con un nombre y una regla. El bucle aplica las reglas en orden (descuento del 10 %, IVA del 21 % y redondeo hacia arriba) y escribe los precios después de cada paso. Cambiar el orden o añadir una regla es tocar solo la tabla, no el bucle.
Los punteros a funciones están por todas partes en C: qsort recibe la función que compara, atexit la que se ejecuta al salir y las bibliotecas de interfaz gráfica, la que responde a cada botón.
Código · main.c
#include <stdio.h>// A type for "a function that takes a double and returns a double".typedef double (*PriceRule)(double);double add_vat(double p) { return p * 1.21; }double discount(double p) { return p * 0.90; }double round_up(double p) { return (int)(p + 0.99); }// apply_all receives a callback: what to do with each price is up to the caller.void apply_all(double *prices, int n, PriceRule rule) { for (int i = 0; i < n; i++) prices[i] = rule(prices[i]);}void print_prices(const char *label, const double *prices, int n) { printf("%-12s", label); for (int i = 0; i < n; i++) printf(" %7.2f", prices[i]); printf("\n");}int main(void) { double prices[] = {10.00, 24.50, 7.95, 99.00}; int n = sizeof prices / sizeof prices[0]; print_prices("Start", prices, n); // A table of named rules: an array of function pointers. struct { const char *name; PriceRule rule; } steps[] = { {"Discount", discount}, {"With VAT", add_vat}, {"Rounded", round_up}, }; for (int s = 0; s < 3; s++) { apply_all(prices, n, steps[s].rule); print_prices(steps[s].name, prices, n); } return 0;}Salida · cc main.c -o main && ./main
Start 10.00 24.50 7.95 99.00 Discount 9.00 22.05 7.16 89.10 With VAT 10.89 26.68 8.66 107.81 Rounded 11.00 27.00 9.00 108.00
Para recordar
typedef R (*Nombre)(params);da nombre al tipo de puntero a función.- El nombre de la función sin
()es su dirección. - Un callback es una función que se pasa a otra para que la llame.
- Una tabla de structs con punteros a funciones sustituye a un
switchlargo.
Ejercicio
Añada la regla psychological, que deja cada precio en x,99 (por ejemplo, 27.00 pasa a 26.99), y póngala al final de la tabla steps.