Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.

Link para esta página de comparações

Ambos lados da revisão anterior Revisão anterior
Próxima revisão
Revisão anterior
prog2:ponteiros_para_funcoes [2019/05/14 15:22]
maziero
prog2:ponteiros_para_funcoes [2020/08/19 15:18] (atual)
maziero [Ponteiros para funções]
Linha 1: Linha 1:
 +====== Ponteiros para funções ======
 +
 +{{ :​prog2:​progc_14_func_ptr.mkv |Video desta aula}}
 +
 +{{ :​prog2:​funcptr.png|https://​www.flaticon.com/​authors/​vitaly-gorbachev}} Em C, uma função é vista como uma referência (ou endereço) para uma área de memória onde se encontra seu código. Por isso, o identificador de uma função pode ser visto como um ponteiro. Funções podem ser acessadas usando ponteiros, de forma similar às variáveis.
 +
 +===== Declaração e uso =====
 +
 +Declarar um ponteiro para uma função é relativamente simples, apesar da sintaxe assustar à primeira vista. O código abaixo declara um ponteiro ''​fp''​ para uma função que tem um parâmetro inteiro e não retorna nada:
 +
 +<code c>
 +// uma função com protótipo "void name (int)"
 +void f (int)
 +
 +  ... 
 +}
 +
 +// um ponteiro para funções com protótipo "void name (int)"
 +void (*fp) (int) ;     
 +</​code>​
 +
 +Observe que os parênteses envolvendo ''​*fp''​ são necessários. Caso sejam omitidos, a declaração acima muda completamente de sentido:
 +
 +<code c>
 +void * fp (int) ; // protótipo de função retornando ''​void*''​
 +</​code>​
 +
 +O uso de ponteiros para funções é simples:
 +
 +<code c funcptr.c>​
 +#include <​stdio.h>​
 +
 +void inc (int *n)
 +{
 +  (*n)++ ;
 +}
 +
 +int main ()
 +{
 +  void (*fp) (int *) ; // function pointer
 +
 +  fp = inc ; // fp points to inc
 +
 +  int a = 0 ;
 +  printf ("a vale %d\n", a) ;
 +
 +  inc(&a) ; // normal call
 +  printf ("a vale %d\n", a) ;
 +
 +  fp(&a) ; // call using the function pointer
 +  printf ("a vale %d\n", a) ;
 +}
 +</​code>​
 +
 +Sua execução resulta em:
 +
 +  a vale 0
 +  a vale 1
 +  a vale 2
 +
 +<note important>​
 +Obviamente, um ponteiro de função só pode apontar para funções que tenham o mesmo protótipo (assinatura) com o qual o ponteiro foi declarado.
 +
 +Caso necessário,​ pode-se fazer //type casting// de ponteiros para funções.</​note>​
 +
 +===== Funções como parâmetros =====
 +
 +Como uma variável pode apontar para uma função, então funções podem ser usadas como parâmetros de outras funções. O código a seguir ilustra como fazer isso:
 +
 +<code c funcparam.c>​
 +#include <​stdio.h>​
 +#include <​string.h>​
 +#include <​ctype.h>​
 +
 +// aplica a função "​func"​ aos caracteres de str
 +void aplica (int (func) (int), char *str)
 +{
 +  for (int i=0; str[i]; i++)
 +    str[i] = func (str[i]) ;
 +}
 +
 +// se c for uma vogal, devolve '​-'​
 +int tira_vogal (int c)
 +{
 +  switch (c)
 +  {
 +    case '​a':​
 +    case '​e':​
 +    case '​i':​
 +    case '​o':​
 +    case '​u':​
 +    case '​A':​
 +    case '​E':​
 +    case '​I':​
 +    case '​O':​
 +    case '​U':​ return ('​-'​) ;
 +    default : return (c) ;
 +   }
 +}
 +
 +int main ()
 +{
 +  char frase[128] ;
 +
 +  strcpy (frase, "Uma frase com MAIUSCULAS e minusculas"​) ;
 +  printf ("​Frase:​ %s\n", frase) ;
 +
 +  aplica (toupper, frase) ;
 +  printf ("​Frase:​ %s\n", frase) ;
 +
 +  aplica (tolower, frase) ;
 +  printf ("​Frase:​ %s\n", frase) ;
 +
 +  aplica (tira_vogal,​ frase) ;
 +  printf ("​Frase:​ %s\n", frase) ;
 +}
 +</​code>​
 +
 +Resultado da execução:
 +
 +<​code>​
 +Frase: Uma frase com MAIUSCULAS e minusculas
 +Frase: UMA FRASE COM MAIUSCULAS E MINUSCULAS
 +Frase: uma frase com maiusculas e minusculas
 +Frase: -m- fr-s- c-m m---sc-l-s - m-n-sc-l-s
 +</​code>​
 +
 +<note tip>
 +Uma função também pode retornar um ponteiro de função. Neste caso, a sintaxe da declaração da função pode ficar complexa, sobretudo se a função tiver parâmetros e a função retornada também.
 +</​note>​
 +
 +/*
 +https://​stackoverflow.com/​questions/​20617067/​returning-function-pointer-type
 +
 +typedef int (*function_type)(int,​int) ;
 +
 +function_type getFunc()
 +{
 +   ​function_type test ;
 +   test = ... ;
 +   ​return test ;
 +}
 +*/
 +
 +===== Exercícios =====
 +
 +  - A função ''​qsort''​ (//man 3 qsort//) aplica o algoritmo //​QuickSort//​ a um vetor de dados de um tipo definido pelo usuário (int, float, struct, ...). Para ser genérica, essa função depende de uma função externa para comparar os elementos do vetor. Escreva um programa que a) crie um vetor de 100 inteiros aleatórios e ordene esse vetor usando a função ''​qsort''​.
 +  - Idem, para um vetor de tipo ''​double''​.
 +  - Idem, para um vetor de //structs// (ordenar por um dos campos do //​struct//​). ​