Programação em C
Prof. Márcio Sarroglia Pinho

Ponteiros para Funções

O uso de ponteiros para funções em C serve principalmente para definir, em tempo de execução, qual função será executada, sem a necessidade de escrever o nome da função, de forma explícita naquele ponto do código.
Em geral, a definição de qual função será executada é feita em um outro ponto do código, fazendo o ponteiro apontar para a função desejada.
Inicialmente, se deve criar um tipo de dado que aponte para uma função, da seguinte forma:
typedef int TIPOFuncaoSemParametros();
Isto define um tipo de dado que permitirá criar um ponteiro para uma funçãio que retorna um int e que não tem parâmetros.
Para outros tipos de função, devem ser criados novos tipos como no exemplo a seguir:
typedef int TIPOFuncaoComParametros (int x, float y);
typedef int TIPOFuncaoSemParametros();
A partir desteste tipos de dados se pode criar ponteiros que apontem para funções compatíveis com cada um dos tipos, como nos exemplos a seguir:
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
TIPOFuncaoSemParametros *PtrParaFuncSemParametros;
TIPOFuncaoComParametros *PtrParaFuncComParametros;

int Print()
{

}

int Load(int x, float z)

{

}

int main()
{

...
PtrParaFuncSemParametros = Print; // define qual para função o ponteiro aponta
...
(*PtrParaFuncSemParametros) (); // realiza a chamada da função através do ponteiro

...
PtrParaFuncComParametros = Load; // define qual para função o ponteiro aponta
...
(*PtrParaFuncComParametros) (3,2.45); // realiza a chamada da função através do ponteiro

}


Exemplos

Teste o exemplo a seguir e verifique o funcionamento dos ponteiros de função.
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// ***************************************************
// Programação de Baixo Nível
// Ponteiros para funções
//
// ***************************************************

#include <stdio.h>

// ***************************************************
// O typedef a seguir cria um tipo chamado 'TipoFuncao' que define um
// tipo de dado que é uma função.
// O que determina o tipo, neste caso é:
// - o tipo de retorno da função;
// - os parâmetros usados na função. Leva-se em conta a quantidade,
// a ordem e o tipo destes parâmetros
typedef int TipoFuncao();


// ***************************************************
// As três funções a seguir são do mesmo tipo de 'TipoFuncao'
// ***************************************************

int Load()
{
// Veja o que significa a macro __FUNCTION__ em
// https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
printf("%s\n", __FUNCTION__);
return 10;
}

int Print()
{
printf("%s\n", __func__);
return 20;
}
int Quit()
{
printf("%s\n", __func__);
return 30;
}
// ***************************************************
// Funcao que recebe um ponteiro para uma função
// 'PonteiroParaUmaFuncao' e uma variável que irá
// armazenar o valor deste ponteiro 'GuardaEnderecoDeUmaFuncao'
// ***************************************************
void SetCallbackFunc(TipoFuncao **GuardaEnderecoDeUmaFuncao, TipoFuncao *PonteiroParaUmaFuncao)
{
*GuardaEnderecoDeUmaFuncao = PonteiroParaUmaFuncao;
}

int main()
{
int opcao, retorno;
// Cria 3 ponteiros que irão apontar para funções do programa
TipoFuncao *ptrF;

// Faz cada um dos ponteiros apontar para uma função diferente

do {
printf("Digite sua opcao(1,2,3) :");
scanf("%d", &opcao);
switch(opcao) {
case 1:
ptrF = Load;
break;
case 2:
ptrF = Print;
break;
case 3:
SetCallbackFunc(&ptrF, Quit);
break;
}
retorno = (*ptrF)(); // chama uma função a partir de ptrF
// e obtem o retorno
printf ("Retorno da função: %d\n\n", retorno);
} while(opcao !=3);
}



Também é possivel usar vetores de ponteiros para guardar as referências para funções. O exemplo a seguir ilustra este uso, implementando o exemplo anterior de uma forma mais 'elegante' e compacta.
 
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// ***************************************************
// Programação de Baixo Nível
// Ponteiros para funções
// Exemplo com vetor de ponteiros
// ***************************************************

#include <stdio.h>

// ***************************************************
// O typedef a seguir cria um tipo chamado 'TipoFuncao' que define um
// tipo de dado que é uma função.
// O que determina o tipo, neste caso é:
// - o tipo de retorno da função;
// - os parâmetros usados na função. Leva-se em conta a quantidade,
// a ordem e o tipo destes parâmetros
typedef int TipoFuncao();

// Cria um vetor de ponteiros para funções do tipo 'TipoFuncao'
TipoFuncao *VetorDeFuncoes[3];

// ***************************************************
// As três funções a seguir são do mesmo tipo de 'TipoFuncao'
// ***************************************************

int Load()
{
// Veja o que significa a macro __FUNCTION__ em
// https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
printf("%s\n", __FUNCTION__);
return 10;
}

int Print()
{
printf("%s\n", __func__);
return 20;
}
int Quit()
{
printf("%s\n", __func__);
return 30;
}
// ***************************************************
// Funcao que recebe um ponteiro (PonteiroParaUmaFuncao)
// para uma função e o 'indice' do 'VetorDeFuncoes'
// no qual será armazenado o ponteiro
// ***************************************************
void SetCallbackFunc(int indice, TipoFuncao *PonteiroParaUmaFuncao)
{
VetorDeFuncoes[indice] = PonteiroParaUmaFuncao;
}
// ***************************************************
int main()
{
int opcao, retorno;

// Faz cada um dos ponteiros do VetorDeFuncoes apontar para
// uma função diferente
SetCallbackFunc(0, Load);
SetCallbackFunc(1, Print);
SetCallbackFunc(2, Quit);

do {
printf("Digite sua opcao(1,2,3) :");
scanf("%d", &opcao);
// chama uma função a partir do vetor e obtem o retorno
retorno = (*VetorDeFuncoes[opcao-1])();
printf ("Retorno da função: %d\n\n", retorno);
} while(opcao !=3);
}


Por fim, no exemplo a seguir, o programa chama funções com parâmetros através de ponteiros.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// ***************************************************
// Programação de Baixo Nível
// Ponteiros para funções
// Exemplo com vetor de ponteiros e parâmetros
// ***************************************************

#include <stdio.h>

// ***************************************************
// O typedef a seguir cria um tipo chamado 'TipoFuncao' que define um
// tipo de dado que é uma função.
// O que determina o tipo, neste caso é:
// - o tipo de retorno da função;
// - os parâmetros usados na função. Leva-se em conta a quantidade,
// a ordem e o tipo destes parâmetros
typedef int TipoFuncao(int x, float y);

// Cria um vetor de ponteiros para funções do tipo 'TipoFuncao'
TipoFuncao *VetorDeFuncoes[3];

// ***************************************************
// As três funções a seguir são do mesmo tipo de 'TipoFuncao'
// ***************************************************

int Load(int x, float z)
{
// Veja o que significa a macro __FUNCTION__ em
// https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
printf("%s\n", __FUNCTION__);
return x*z;
}

int Print(int x, float z)
{
printf("%s\n", __func__);
return x*z;
}
int Quit(int x, float z)
{
printf("%s\n", __func__);
return x*z;
}
// ***************************************************
// Funcao que recebe um ponteiro (PonteiroParaUmaFuncao)
// para uma função e o 'indice' do 'VetorDeFuncoes'
// no qual será armazenado o ponteiro
// ***************************************************
void SetCallbackFunc(int indice, TipoFuncao *PonteiroParaUmaFuncao)
{
VetorDeFuncoes[indice] = PonteiroParaUmaFuncao;
}
// ***************************************************
int main()
{
int opcao, retorno;

// Faz cada um dos ponteiros do VetorDeFuncoes apontar para
// uma função diferente
SetCallbackFunc(0, Load);
SetCallbackFunc(1, Print);
SetCallbackFunc(2, Quit);

do {
printf("Digite sua opcao(1,2,3) :");
scanf("%d", &opcao);
// chama uma função a partir do vetor, passando os
// parâmetros necessário e obtem o retorno
retorno = (*VetorDeFuncoes[opcao-1])(opcao, opcao*4);
printf ("Retorno da função: %d\n\n", retorno);
} while(opcao !=3);
}


FIM.