Lenguaje C Punteros A Funciones

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 8

Tutorial: punteros a funciones en C | robologs https://robologs.

net/2019/05/31/tutorial-punteros-a-funciones-en-c/

(https://robologs.net/)

| |

Posted on May 31, 2019 (https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/) by Tr4nsduc7or (https://robologs.net/author


/7472616e73647563746f72/)

(Última revisión 22/09/2020)

Saludos, humano. Como sabrás, cuándo programamos en C disponemos de punteros a varios tipos de datos (char*, int*, float*, double*) que nos permiten
hacer muchas cosas: reservar memoria dinámica, crear referencias y alias, etc. Lo que quizá no sabías es que también podemos crear punteros que
apunten a funciones como si fueran cualquier otro tipo de datos.

En los ejemplos de este tutorial verás cómo declarar punteros a funciones y como utilizarlos de varias formas distintas.

He aquí un ejemplo básico. Tenemos una función que escribe un texto por pantalla, y la llamamos a través de un puntero:

1 de 8 13/03/2021 17:34
Tutorial: punteros a funciones en C | robologs https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/
01
02 #include <stdio.h>
03
04 //Funcion de ejemplo
05 void funcion()
06 {
07 printf("Se ha entrado en la funcion\n");
08 }
09
10 int main()
11 {
12 //Creamos el puntero a la funcion
13 void (*puntero_funcion)() = &funcion;
14
15 //Llamamos la funcion a traves del puntero
16 puntero_funcion();
17
18 return 0;
}

Como puedes ver, no tiene demasiada diferencia con el resto de punteros. Vamos a complicarlo un poco más…

Si la función a la que quieres apuntar recibe algún parámetro, hay que indicar sus tipos al declarar el puntero. Fíjate en este ejemplo: la función recibe dos
enteros y muestra sus valores. Nótese que cuándo se declara el puntero se escriben los tipos de los argumentos entre paréntesis.

01
02 #include <stdio.h>
03
04 //Funcion que recibe dos enteros
05 void funcion(int valor1, int valor2)
06 {
07 printf("Valor 1 = %d\n", valor1);
08 printf("Valor 2 = %d\n", valor2);
09 }
10
11 int main()
12 {
13 //Se crea el puntero a la funcion. Hay que indicar el tipo de los parametros que recibe.
14 void (*puntero_funcion)(int, int) = &funcion;
15
16 //Se llama la funcion a traves del puntero
17 puntero_funcion(2, 5);
18
19 return 0;
}

Las funciones también pueden pasarse como parámetros a otras funciones. En este código se define una función principal que recibe como parámetros
dos números a, b y un puntero a una función entera. La función principal pasa a y b como parámetros a la función del puntero y escribe el valor que
devuelve por pantalla.

2 de 8 13/03/2021 17:34
Tutorial: punteros a funciones en C | robologs https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/
01
02 #include <stdio.h>
03
04 int sumar(int a, int b)
05 {
06 return a+b;
07 }
08
09 int restar(int a, int b)
10 {
11 return a-b;
12 }
13
14 void funcion_principal(int a, int b, int (*funcion)(int, int))
15 {
16 int resultado = funcion(a,b);
17 printf("El resultado es %d\n", resultado);
18 }
19
20 int main()
21 {
22 //Se definen dos valores enteros cualesquiera
23 int num1 = 5;
24 int num2 = 4;
25
26 //Se invoca la funcion principal, pasandole la funcion de SUMA
27 printf("\nSuma:\n");
28 funcion_principal(num1, num2, sumar);
29
30 //Se invoca la funcion principal, pasandole la funcion de RESTA
31 printf("Resta:\n");
32 funcion_principal(num1, num2, restar);
33
34 return 0;
}

Con este ejemplo puede verse que los punteros a funciones sirven para eliminar la redundancia en el código: al pasar la función como parámetro nos
ahorramos tener que escribir variantes de la función principal para realizar cada una de las operaciones.

Un ejemplo práctico del caso anterior es la función qsort(). Esta función propia de C permite ordenar cualquier vector utilizando el algoritmo Quick Sort
(https://es.wikipedia.org/wiki/Quicksort). La signatura de la función qsort() en C es:

1
void qsort (void* array, size_t nelementos, size_t bytes, int (*comparador)(const void*,const void*));

dónde void* array es un puntero al vector que se quiere ordenar, nelementos es el número de elementos dentro del vector y bytes es el tamaño que
ocupan.

El parámetro más importante es el último: el puntero a la función comparador. Para ordenar un vector hace falta un criterio para comparar dos elementos
y decidir cuál de ellos va primero. Por ejemplo, en el caso de que los elementos del vector sean enteros, basta con comparar sus valores. Pero ordenar
alfabéticamente un vector de Strings (u otro tipo de estructura más compleja) puede requerir de funciones más elaboradas.

La función qsort() de C está pensada para poder ordenar un vector de cualquier tipo, y para ello el programador debe pasarle como parámetro la función
para comparar elementos. Puedes programar esta función comparadora a tu gusto, pero debe recibir como argumentos dos punteros void
(correspondientes a dos elementos del vector) y devolver 1 o -1 según cuál de los dos elementos vaya primero.

1
2 int comparador(const void * a, const void * b)
3 {
4 //Tu codigo aqui dentro. Tiene que comparar a,b y devolver -1 ó 1.
}

Esta función tendrás que pasarla como parámetro a qsort().

Admito que esto puede parecer complicado a primera vista, pero en realidad es muy sencillo. Veamos un ejemplo: supón que tenemos un struct

3 de 8 13/03/2021 17:34
Tutorial: punteros a funciones en C | robologs https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/
correspondiente a la información de un envase de un cierto producto. Este struct tiene definidos tres campos: un identificador, la capacidad (en mililitros)
del envase y su precio. Si quisiéramos ordenar un vector de envases con la función qsort(), habría que definir una función para comparar dos envases. En
este ejemplo esto se hace de dos formas distintas: por identificador y según el precio por unidad de volumen.

4 de 8 13/03/2021 17:34
Tutorial: punteros a funciones en C | robologs https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/
001
002 #include <stdio.h>
003
004 struct Envase
005 {
006 int id; //Identificador
007 int volumen; //Volumen en mililitros
008 float precio; //Precio en euros
009 };
010
011 /* Metodo de ordenacion I: ordenar por identificador*/
012 int ordenarID (const void * a, const void * b)
013 {
014 /*Se hace un casting para convertir los punteros void a punteros de Envases
015 y se guarda su identificador*/
016 int id_a = ((struct Envase*)a)->id;
017 int id_b = ((struct Envase*)b)->id;
018
019 //Se comparan los dos identificadores
020 if(id_a > id_b)
021 return 1;
022
023 else
024 return -1;
025 }
026
027
028 /* Metodo de ordenacion II: ordenar por precio/unidad de volumen */
029 int ordenar_precio_volumen (const void * a, const void * b)
030 {
031 /*Se hace un casting para convertir los punteros void a punteros de Envases
032 y se guarda su volumen y precio*/
033 float precio_a = ((struct Envase*)a)->precio;
034 int volumen_a = ((struct Envase*)a)->volumen;
035 float precio_b = ((struct Envase*)b)->precio;
036 int volumen_b = ((struct Envase*)b)->volumen;
037
038 //Se calcula precio/volumen
039 float val_a = precio_a/volumen_a;
040 float val_b = precio_b/volumen_b;
041
042 //Se comparan los dos valores
043 if(val_a > val_b)
044 return 1;
045
046 else
047 return -1;
048 }
049
050
051 int main()
052 {
053 int dimension = 4; //Dimension del vector
054
055 struct Envase array[4]; //Vector de envases
056
057 array[0].id = 5;
058 array[0].volumen = 600;
059 array[0].precio = 12;
060
061 array[1].id = 6;
062 array[1].volumen = 550;
063 array[1].precio = 7.99;
064
065 array[2].id = 1;
066 array[2].volumen = 400;
067 array[2].precio = 25;
068
069 array[3].id = 3;
070 array[3].volumen = 600;
071 array[3].precio = 9.5;
072
073
5 de 8 13/03/2021 17:34
Tutorial: punteros a funciones en C | robologs https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/
074 //Ordenar el vector por ID
075 qsort((void*)array, dimension, sizeof(struct Envase), ordenarID);
076
077
078 //Mostrar el vector por ID. El output es {1 3 5 6}
079 printf("\nOrdenado por ID: {");
080 for(int i = 0; i < dimension; i++)
081 {
082 printf("%d ", array[i].id);
083 }
084 printf("}\n");
085
086
087 //Ordenar el vector por precio/volumen
088 qsort((void*)array, dimension, sizeof(struct Envase), ordenar_precio_volumen);
089
090
091 //Mostrar el vector por precio/volumen. El output ahora es {6 3 5 1}
092 printf("\nOrdenado por precio/vol: {");
093 for(int i = 0; i < dimension; i++)
094 {
095 printf("%d ", array[i].id);
096 }
097 printf("}\n\n");
098
099
100 return 0;
101 }

Como es lógico, puedes hacer funciones comparadoras tan complicadas como quieras. Este es uno de los puntos fuertes del lenguaje C, su enorme
flexibilidad.

C también permite declarar arrays de punteros a funciones. Este código define tres funciones para hacer comprobaciones sobre un número (si es par, si es
positivo y si es primo) y las realiza sobre un entero introducido por el usuario. La gracia es que en vez de llamar las tres funciones individualmente, se
guardan en un vector y éste se recorre con un bucle for.

6 de 8 13/03/2021 17:34
Tutorial: punteros a funciones en C | robologs https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/
01
02 #include <stdio.h>
03
04 /*Comprobar si el numero es PAR*/
05 void funcion1(int a)
06 {
07 if(a % 2 == 0)
08 printf("El numero es par\n");
09 else
10 printf("El numero es impar\n");
11 }
12
13
14 /*Comprobar si el numero es POSITIVO/NEGATIVO*/
15 void funcion2(int a)
16 {
17 if(a > 0)
18 printf("El numero es positivo\n");
19 else if(a < 0)
20 printf("El numero es negativo\n");
21 else
22 printf("El numero es cero\n");
23 }
24
25
26 /*Comprobar si el numero es PRIMO*/
27 void funcion3(int a)
28 {
29 if(a <= 1)
30 {
31 printf("El numero NO es primo\n");
32 return;
33 }
34
35 for(int i = 2; i <= (a)/2; i++)
36 {
37 if ( a%i == 0 )
38 {
39 printf("El numero NO es primo\n");
40 return;
41 }
42 }
43 printf("El numero es primo\n");
44 }
45
46 int main()
47 {
48
49
50 //Vector de funciones
51 void (*array[]) (int) = {funcion1, funcion2, funcion3};
52
53 //Se pide al usuario que entre un numero
54 int val;
55 printf("\nIntroduce un numero entero: ");
56 scanf("%d", &val);
57
58 //Se recorre el vector para llamar las funciones
59 for(int i = 0; i < 3; i++)
60 {
61 array[i] (val);
62 }
63
64 return 0;
}

7 de 8 13/03/2021 17:34
Tutorial: punteros a funciones en C | robologs https://robologs.net/2019/05/31/tutorial-punteros-a-funciones-en-c/

© 2021 robologs. All rights reserved. Hiero (https://athemes.com/theme/hiero/) by aThemes

8 de 8 13/03/2021 17:34

También podría gustarte