Da trilha de C Este conceito ainda não saiu como card do dia. ir para o card de hoje

C Memória Intermediário

Ponteiros e funções

Em C, todos os argumentos são passados por valor: a função recebe uma cópia. Para que uma função modifique uma variável do chamador, passamos o endereço dela com & e a função recebe um ponteiro. Assim, *p = 10 altera a variável original — isso é o que chamamos de passagem por referência simulada.

Ponteiros também permitem que uma função "retorne" mais de um valor: em vez de usar return, ela escreve nos endereços recebidos. Por exemplo, void minmax(int *v, int n, int *min, int *max) devolve dois resultados de uma vez.

O qualificador const documenta a intenção: const int *p é ponteiro para dado constante (não pode alterar o valor apontado), int *const p é ponteiro constante (não pode apontar para outro lugar) e const int *const p proíbe ambos. Já int **pp é um ponteiro para ponteiro, útil quando a função precisa alterar o próprio ponteiro do chamador, como em alocar(&ptr).

Pontos-chave

  • Passagem por referência em C é feita passando &variavel; a função recebe um ponteiro e escreve com *p.
  • Uma função pode devolver vários valores escrevendo em ponteiros de saída passados pelo chamador.
  • const int *p protege o dado apontado; int *const p protege o próprio ponteiro.
  • int **pp permite que a função modifique o ponteiro original do chamador.
  • Sempre inicialize ponteiros e só desreferencie endereços válidos.
ponteiros_funcoes.c
#include <stdio.h>

/* Troca dois inteiros usando ponteiros (passagem por referência). */
void troca(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

/* Devolve dois resultados via ponteiros de saída. */
void minmax(const int *v, int n, int *min, int *max) {
    *min = *max = v[0];
    for (int i = 1; i < n; i++) {
        if (v[i] < *min) *min = v[i];
        if (v[i] > *max) *max = v[i];
    }
}

/* Altera o ponteiro do chamador usando ponteiro para ponteiro. */
void apontar_para_maior(int *a, int *b, int **destino) {
    *destino = (*a >= *b) ? a : b;
}

int main(void) {
    int x = 3, y = 7;
    troca(&x, &y);
    printf("x=%d y=%d\n", x, y);

    int v[] = {4, -1, 9, 2};
    int menor, maior;
    minmax(v, 4, &menor, &maior);
    printf("menor=%d maior=%d\n", menor, maior);

    int *p = NULL;
    apontar_para_maior(&x, &y, &p);
    printf("maior=%d\n", *p);
    return 0;
}

Exercícios

  1. 1
    Fácil

    Dobrar um valor por referência

    Escreva uma função void dobrar(int *n) que multiplica por 2 o inteiro apontado por n. No main, leia um inteiro, chame dobrar passando o endereço e imprima o resultado.

    Resolver
  2. 2
    Médio

    Divisão inteira com resto via ponteiros de saída

    Implemente void divmod(int a, int b, int *q, int *r) que calcula o quociente e o resto da divisão inteira de a por b e os escreve em *q e *r. Trate b == 0 imprimindo erro e retornando sem alterar as saídas. No main, leia a e b e imprima q=<q> r=<r>.

    Resolver
  3. 3
    Desafio

    Busca em vetor com ponteiro para ponteiro e `const`

    Escreva const int *buscar_maior(const int *v, int n, int **pos) que retorna um ponteiro para o maior elemento de v e escreve em *pos o índice desse elemento. Use const int * no parâmetro e no retorno (o vetor não deve ser modificado). No main, leia n, depois n inteiros, chame a função e imprima maior=<valor> pos=<indice>.

    Resolver

Continue estudando