Desafio C

Busca em vetor com ponteiro para ponteiro e `const`

Enunciado

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

Requisitos

  • O parâmetro e o retorno usam const int *.
  • O índice é devolvido via int **pos (ponteiro para ponteiro).
  • A função não altera o vetor.
  • Saída no formato maior=<valor> pos=<indice>.

Código inicial

#include <stdio.h>

const int *buscar_maior(const int *v, int n, int **pos) {
    /* complete */
}

int main(void) {
    int n;
    scanf("%d", &n);
    int v[100];
    for (int i = 0; i < n; i++) scanf("%d", &v[i]);
    /* chame e imprima */
    return 0;
}

Saída esperada

maior=9 pos=2
Ver dica

Use uma variável int idx no main e passe &idx? Cuidado: o parâmetro é int **, então você precisa de um int *p = &idx; e passar &p.

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

/* Retorna ponteiro para o maior e escreve o índice via int **pos. */
const int *buscar_maior(const int *v, int n, int **pos) {
    int idx = 0;                       /* índice do maior até agora */
    for (int i = 1; i < n; i++) {
        if (v[i] > v[idx]) idx = i;    /* só lê, nunca escreve no vetor */
    }
    **pos = idx;                       /* grava o índice no int apontado */
    return &v[idx];                    /* ponteiro para o maior elemento */
}

int main(void) {
    int n;
    scanf("%d", &n);
    int v[100];
    for (int i = 0; i < n; i++) scanf("%d", &v[i]);

    int idx = -1;          /* variável que receberá o índice */
    int *p = &idx;         /* ponteiro para idx */
    const int *maior = buscar_maior(v, n, &p);  /* passamos &p: int ** */

    printf("maior=%d pos=%d\n", *maior, idx);
    return 0;
}

Passo a passo

  1. const int *v promete que a função não modifica o vetor; const int * no retorno promete o mesmo sobre o elemento devolvido.
  2. int **pos é um ponteiro para o ponteiro do chamador; permite alterar para onde p aponta, se necessário.
  3. int idx = 0; guarda o índice do maior visto até agora.
  4. O laço compara v[i] com v[idx] e atualiza idx quando encontra algo maior.
  5. **pos = idx; desreferencia duas vezes: primeiro chega ao int *p do main, depois ao int idx.
  6. return &v[idx]; devolve o endereço do maior elemento, sem copiar o valor.
  7. No main, int *p = &idx; e buscar_maior(v, n, &p) passam int **.
  8. printf imprime o valor apontado (*maior) e o índice já atualizado (idx).

Por que funciona

O retorno const int * dá acesso somente leitura ao elemento, evitando cópias. O int ** permite que a função escreva no int do chamador através de dois níveis de indireção: *pos é o ponteiro p, **pos é o int idx. O const no parâmetro documenta e garante que o vetor original não é alterado.

Erros comuns

  • **pos = idx; trocado por *pos = &idx;: atribui um int * a um int, gerando aviso/erro e resultado errado.
  • Passar &idx diretamente (tipo int *) para um parâmetro int **: o compilador avisa e o comportamento é indefinido.
  • Retornar &v[idx] sem const no tipo de retorno: atribuir a const int * funciona, mas o contrato de não escrita fica implícito; mantenha o const.
  • Esquecer de inicializar idx no main: se n == 0, o printf lê lixo.

Outra forma de resolver

Sem ponteiro para ponteiro, devolvemos o índice por return e o valor por um int *: int buscar_maior(const int *v, int n, int *valor). É mais simples, mas não exercita int **. Use int ** quando a função precisa realocar ou reapontar o ponteiro do chamador (por exemplo, em alocar(&ptr)).

Saída esperada

maior=9 pos=2