Ponteiros para Funções em C: Exemplos Práticos e Melhores Práticas
Ponteiros para funções desbloqueiam capacidades poderosas em C, permitindo que funções manipulem dados diretamente através de endereços de memória em vez de copiar valores. Ao passar endereços para parâmetros de ponteiro, uma função pode modificar as variáveis originais, permitindo padrões como troca in-place, callbacks dinâmicos e funções de ordem superior.
- Exemplo de Ponteiros para Funções
- Funções com Parâmetros de Array
- Funções que Retornam um Array
- Ponteiros para Funções
- Array de Ponteiros para Funções
- Funções Usando Ponteiros Void
- Ponteiros para Funções como Argumentos
Exemplo de Ponteiros para Funções
A rotina clássica de troca demonstra como uma função pode trocar os valores de duas variáveis operando em seus endereços.
void swap (int *a, int *b);
int main() {
int m = 25;
int n = 100;
printf("m é %d, n é %d\n", m, n);
swap(&m, &n);
printf("m é %d, n é %d\n", m, n);
return 0;
}
void swap (int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
Saída:
m é 25, n é 100 m é 100, n é 25
- Declare
swapcom dois ponteiros inteiros. - Inicialize
menemmaine imprima-os. - Chame
swap(&m, &n)para passar os endereços. - Dentro de
swap, use uma variável temporária para trocar os valores. - Desreferencie ponteiros para ler/escrever os dados reais.
Funções com Parâmetros de Array
Arrays decaem para ponteiros quando passados para funções. O programa a seguir soma os elementos de um array iterando sobre o ponteiro.
int add_array (int *a, int num_elements);
int main() {
int Tab[5] = {100, 220, 37, 16, 98};
printf("Soma total é %d\n", add_array(Tab, 5));
return 0;
}
int add_array (int *p, int size) {
int total = 0;
for (int k = 0; k < size; k++) {
total += p[k]; /* equivalente a total += *p; p++; */
}
return total;
}
Saída:
Soma total é 471
- Defina
add_arraypara aceitar um ponteiro e tamanho, retornando a soma. - Passe o nome do array
Tab(que decai para ponteiro) e seu comprimento para a função.
Funções que Retornam um Array
Uma função pode retornar um ponteiro para um array estático. Essa abordagem é útil quando o chamador precisa de um array temporário sem gerenciar alocação de memória.
#include <stdio.h>
int * build_array();
int main() {
int *a;
a = build_array(); /* obtém os 5 primeiros números pares */
for (int k = 0; k < 5; k++)
printf("%d\n", a[k]);
return 0;
}
int * build_array() {
static int Tab[5] = {1,2,3,4,5};
return Tab;
}
Saída:
1 2 3 4 5
- Declare uma função que retorna um ponteiro para um array estático.
- Use o ponteiro retornado para iterar e imprimir o conteúdo do array.
Ponteiros para Funções
Um ponteiro para função guarda o endereço do ponto de entrada de uma função, permitindo despacho dinâmico e callbacks. A sintaxe de declaração requer parênteses em torno do asterisco para evitar interpretação incorreta.
tipo_retorno (*nome_funcao)(argumentos)
Exemplo: Chame uma rotina através de um ponteiro.
#include <stdio.h>
void Hi_function (int times); /* função */
int main() {
void (*function_ptr)(int); /* ponteiro para função */
function_ptr = Hi_function; /* atribuição */
function_ptr(3); /* invocação */
return 0;
}
void Hi_function (int times) {
for (int k = 0; k < times; k++)
printf("Hi\n");
}
Saída:
Hi Hi Hi
- Defina uma função regular.
- Declare um ponteiro para função com a assinatura correta.
- Atribua o ponteiro ao nome da função.
- Invoque a função através do ponteiro.
Array de Ponteiros para Funções
Armazenar múltiplos ponteiros para funções em um array permite uma abordagem orientada a tabela, semelhante a uma instrução switch. O programa a seguir demonstra uma calculadora simples.
#include <stdio.h>
int sum(int num1, int num2);
int sub(int num1, int num2);
int mult(int num1, int num2);
int divi(int num1, int num2);
int main() {
int x, y, choice, result;
int (*ope[4])(int, int);
ope[0] = sum;
ope[1] = sub;
ope[2] = mult;
ope[3] = divi;
printf("Digite dois números inteiros: ");
scanf("%d%d", &x, &y);
printf("Digite 0 para somar, 1 para subtrair, 2 para multiplicar ou 3 para dividir: ");
scanf("%d", &choice);
result = ope[choice](x, y);
printf("%d", result);
return 0;
}
int sum(int x, int y) {return x + y;}
int sub(int x, int y) {return x - y;}
int mult(int x, int y) {return x * y;}
int divi(int x, int y) {return y != 0 ? x / y : 0;}
Resultado: Entrada 13 48 2 → 624
- Defina quatro funções aritméticas.
- Crie um array de quatro ponteiros para funções com assinaturas correspondentes.
- Atribua cada ponteiro à função correspondente.
- Obtenha a escolha do usuário e chame a função selecionada.
Funções Usando Ponteiros Void
Ponteiros void fornecem acesso agnóstico a tipo de dados. Quando usados em parâmetros de função, permitem que a rotina aceite qualquer tipo de dados, desde que o chamador forneça o cast correto.
void * cube (const void *);
Programa de exemplo:
#include <stdio.h>
void* cube (const void* num);
int main() {
int x = 4;
int cube_int = (int)cube(&x);
printf("%d ao cubo é %d\n", x, cube_int);
return 0;
}
void* cube (const void *num) {
int result = (*(int *)num) * (*(int *)num) * (*(int *)num);
return (void*)result;
}
Resultado: 4 ao cubo é 64
- Defina uma função que aceita um ponteiro void const e retorna um ponteiro void.
- Converta o ponteiro para
int *para acessar o valor. - Calcule o cubo e converta o resultado de volta para
void *para retorno.
Ponteiros para Funções como Argumentos
Passar um ponteiro para função para outra função é um padrão comum para callbacks. A biblioteca padrão qsort usa essa técnica para ordenar arrays de tipos arbitrários.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *));
Exemplo que ordena um array de inteiros:
#include <stdio.h>
#include <stdlib.h>
int compare (const void *, const void *);
int main() {
int arr[5] = {52, 14, 50, 48, 13};
size_t num = sizeof(arr)/sizeof(arr[0]);
size_t width = sizeof(arr[0]);
qsort((void *)arr, num, width, compare);
for (size_t i = 0; i < num; i++)
printf("%d ", arr[i]);
return 0;
}
int compare (const void *elem1, const void *elem2) {
int a = *(int *)elem1;
int b = *(int *)elem2;
return (a - b);
}
Resultado: 13 14 48 50 52
- Implemente
comparepara retornar negativo, zero ou positivo baseado nos dois inteiros. - Determine o tamanho do array e largura do elemento com
sizeof. - Chame
qsortcom o array, contagem, largura e função de comparação. - Imprima o array ordenado para verificar a operação.
Linguagem C
- Quatro Padrões Comprovados para Funções Definidas pelo Usuário em C
- Laço do-while em C++: Sintaxe, Exemplos Práticos e Loops Aninhados
- Dominando Ponteiros em C++: Conceitos, Exemplos e Aplicações Práticas
- Sobrecarga de Operadores em C++: Guia Prático com Exemplos de Código
- Funções em C++ Explicadas com Exemplos Práticos de Código
- Dominando Collections em C#: Tutorial Prático com Exemplos do Mundo Real
- Ponteiros em C: Guia Completo sobre Tipos, Uso e Melhores Práticas
- Domine o str.count() do Python: Como Contar Caracteres e Substrings com Exemplos
- Dominando Funções Lambda em Python: Exemplos Práticos e Boas Práticas
- Função round() em Python Explicada com Exemplos Práticos