Ponteiro de funções em C
-
Utilize
void (*func)()
Notação para definir ponteiro de função em C - Utilizar a Function Pointer Array para implementar a função de programação genérica do tipo
Este artigo irá introduzir como utilizar um ponteiro de função em C.
Utilize void (*func)()
Notação para definir ponteiro de função em C
Os apontadores de funções são mais uma construção na programação em C que implementam características avançadas como a chamada dinâmica de funções, estruturas que incluem os seus próprios métodos semelhantes ao design orientado para objectos, programação genérica de tipo e etc. Note-se que a declaração do ponteiro de função pode ter uma sintaxe complicada, nomeadamente, void (*func)(void)
notação declara o ponteiro para a função void
que não toma parâmetros. Embora atribuamos o endereço da função printInt
, isso leva um único argumento int
à função void (*func)(void)
tipo ponteiro de função no exemplo seguinte. Uma vez definido o ponteiro de função chamado func
, pode ser chamado com a notação habitual de chamada de função func(arg)
ou com o operador de desreferenciação (*func)(arg)
.
#include <stdio.h>
#include <stdlib.h>
void printInt(int x) { printf("printed from printInt: %d\n", x); }
int main() {
int input1 = 10233;
void (*func)(int) = printInt;
func(input1);
(*func)(input1);
exit(EXIT_SUCCESS);
}
Resultado:
printed from printInt: 10233
printed from printDouble: 11.234000
Em alternativa, podemos definir um novo tipo de pseudónimo de um ponteiro de função utilizando typedef
para tornar o código mais legível. Note-se que tipos diferentes de funções precisariam de declarações separadas de typedef
. Na seguinte amostra de código, definimos um ponteiro para uma função vazia sem quaisquer argumentos; no entanto, tanto os endereços das funções printInt
como printDouble
são armazenados na variável do tipo FuncPtr
. É de notar que o endereço da função específica pode ser tomado com operador explícito &
ou com a atribuição implícita do próprio nome da função, como demonstrado no exemplo seguinte.
#include <stdio.h>
#include <stdlib.h>
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func1 = printInt;
FuncPtr func2 = printDouble;
func1(input1);
func2(input2);
exit(EXIT_SUCCESS);
}
Resultado:
printed from printInt: 10233
printed from printDouble: 11.234000
Utilizar a Function Pointer Array para implementar a função de programação genérica do tipo
Como outros objectos, pode-se definir um array de apontadores de funções com parênteses []
notação. Esta matriz pode ser utilizada para escolher e chamar facilmente funções específicas durante o tempo de execução. Note-se que estamos a utilizar a palavra-chave _Generic
, que é switch
, como uma expressão que permite ao utilizador escolher o caso específico com base na avaliação do tipo da expressão de controlo. Consequentemente, implementamos o seguinte exemplo de código, onde a função print
correspondente é chamada com base no tipo da variável passada na condição switch
. Note-se que, o tipo enum
também é utilizado para definir valores constantes para diferentes casos.
#include <stdio.h>
#include <stdlib.h>
enum TYPE { INTEGER, DOUBLE, INVALID };
#define typename(x) \
_Generic((x), int: INTEGER, double: DOUBLE, default: INVALID)
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func_ptrs[] = {printInt, printDouble};
switch (typename(input1)) {
case INTEGER:
func_ptrs[INTEGER](input1);
break;
case DOUBLE:
func_ptrs[DOUBLE](input1);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
switch (typename(input2)) {
case INTEGER:
func_ptrs[INTEGER](input2);
break;
case DOUBLE:
func_ptrs[DOUBLE](input2);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
exit(EXIT_SUCCESS);
}
Resultado:
printed from printInt: 10233
printed from printDouble: 11.234000
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook