Ponteiros para funções

Uma função é vista como uma referência para uma área de memória na qual reside seu código e 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.

Declarar um ponteiro para uma função é relativamente simples. O código abaixo declara um ponteiro ''fp'' para uma função que tem um parâmetro inteiro e retorna um inteiro.

int f (int) { ... } ; // função com protótipo "int function (int);"

int (*fp) (int) ;     // ponteiro para função com protótipo "int function (int)"

Observe que os parênteses envolvendo ''*fp'' são necessários. Caso sejam omitidos, a declaração acima muda completamente de sentido:

int * fp (int) ;      // protótipo de função que retorna um int*

O uso de ponteiros para funções também é simples:

#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) ;

   return (0) ;
}

Sua execução resulta em:

  a vale 0
  a vale 1
  a vale 2

Funções podem ser usadas como parâmetros de outras funções, através de ponteiros.

#include <stdio.h>

#define SIZE 10

// divides value by 2
void half (float *a)
{
   (*a) /= 2.0 ;
}

// multiplies value by 2
void twice (float *a)
{
   (*a) *= 2.0 ;
}

// applies function "func" to all elements of vector "v"
void apply (float *v, int n, void (*func) (float*))
{
   int i ;
   for (i=0; i< n; i++)
      func (&v[i]) ;
}

// prints a float vector
void printv (float *v, int n)
{
   int i ;
   for (i=0; i<n; i++)
      printf ("%6.1f", v[i]) ;
   printf ("\n") ;
}

int main ()
{
   float vet[SIZE] ;
   int i ;

   for (i=0; i<SIZE; i++)
      vet[i] = i*10 ;

   printv (vet, SIZE) ;

   // applies the function "half" to the vector
   apply (vet, SIZE, half) ;

   printv (vet, SIZE) ;

   // applies the function "twice" to the vector
   apply (vet, SIZE, twice) ;

   printv (vet, SIZE) ;

   return (0) ;
}

Resultado da execução:

   0.0  10.0  20.0  30.0  40.0  50.0  60.0  70.0  80.0  90.0
   0.0   5.0  10.0  15.0  20.0  25.0  30.0  35.0  40.0  45.0
   0.0  10.0  20.0  30.0  40.0  50.0  60.0  70.0  80.0  90.0

Exercícios

  1. 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''.

  2. Idem, para um vetor de tipo ''double''.

  3. Idem, para um vetor de structs (ordenar por um dos campos do struct).