Desafio C

Inverter array in-place com dois ponteiros

Enunciado

Escreva uma função void inverter(int *v, int n) que inverta os elementos de um array in-place, usando dois ponteiros (um do início, outro do fim). No main, aplique ao array {1, 2, 3, 4, 5} e imprima o resultado separado por espaços.

Requisitos

  • A função deve receber int *v e int n.
  • Usar dois ponteiros que se movem para o centro, trocando os valores.
  • Não usar array auxiliar.
  • Imprimir os elementos na ordem invertida.

Código inicial

#include <stdio.h>

void inverter(int *v, int n) {
    /* use dois ponteiros para trocar os elementos */
}

int main(void) {
    int v[5] = {1, 2, 3, 4, 5};
    /* chame inverter e imprima */
    return 0;
}

Saída esperada

5 4 3 2 1
Ver dica

Comece com int *esq = v; e int *dir = v + n - 1;. Enquanto esq < dir, troque *esq e *dir e mova os dois.

Mostrar solução
#include <stdio.h>

void inverter(int *v, int n) {
    int *esq = v;               /* aponta para o primeiro */
    int *dir = v + n - 1;       /* aponta para o ultimo */

    while (esq < dir) {
        int tmp = *esq;         /* troca os valores apontados */
        *esq = *dir;
        *dir = tmp;
        esq++;                  /* avanca para o centro */
        dir--;
    }
}

int main(void) {
    int v[5] = {1, 2, 3, 4, 5};

    inverter(v, 5);             /* v decai para int * */

    for (int i = 0; i < 5; i++) {
        printf("%d%s", v[i], i < 4 ? " " : "\n");
    }
    return 0;
}

Passo a passo

  1. int *esq = v; aponta para o primeiro elemento.
  2. int *dir = v + n - 1; usa aritmética para apontar para o último.
  3. O while (esq < dir) compara endereços: continua enquanto os ponteiros não se cruzarem.
  4. Salvamos *esq em tmp, copiamos *dir para *esq e tmp para *dir, trocando os valores.
  5. esq++ e dir-- aproximam os ponteiros do centro.
  6. No main, inverter(v, 5) passa o endereço do primeiro elemento; a função altera o array original.
  7. O laço final imprime os valores já invertidos.

Por que funciona

A função recebe um ponteiro, então trabalha diretamente na memória do array do main — sem cópia. A aritmética de ponteiros permite calcular o último elemento como v + n - 1 e comparar posições com <. A troca via * altera os valores no local, cumprindo o requisito de inverter in-place.

Erros comuns

  • Usar while (esq <= dir) em arrays de tamanho ímpar: o elemento do meio seria trocado consigo mesmo, o que é inofensivo, mas em pares pode causar troca dupla. Prefira <.
  • Esquecer n - 1 em dir = v + n: aponta para uma posição além do array.
  • Trocar os ponteiros em vez dos valores: int *t = esq; esq = dir; dir = t; só muda as variáveis locais, não o array.
  • Passar inverter(&v, 5) em vez de inverter(v, 5): &v tem tipo int (*)[5], incompatível com int *.

Outra forma de resolver

Usar índices em vez de ponteiros:

for (int i = 0, j = n - 1; i < j; i++, j--) {
    int tmp = v[i]; v[i] = v[j]; v[j] = tmp;
}

É equivalente, porque v[i] é *(v + i). A versão com ponteiros deixa explícita a caminhada na memória.

Saída esperada

5 4 3 2 1