Qual o problema da função troca abaixo?
void troca (int *i, int *j) {
int *temp;
*temp = *i;
*i = *j;
*j = *temp;
}
void troca (int *i, int *j) {
int *temp;
*temp = *i;
*i = *j;
*j = *temp;
}
Passo 1
O enunciado dá uma função em C e pergunta qual é o problema dela. O código fornecido é:
void troca (int *i, int *j) {
int *temp;
*temp = *i;
*i = *j;
*j = *temp;
}
O que se quer saber: qual é o erro desse código e por que ele está errado.
Passo 2
O que a função deveria fazer (intuição): trocar os valores inteiros armazenados nas posições apontadas por
i e j. Ou seja, se i aponta para uma variável a com valor 3 e j aponta para uma variável b com valor 5, após a chamada troca(&a,&b) espera-se a == 5 e b == 3.Passo 3
Noções básicas de ponteiros e desreferência (explicação didática)
- Um
int *pé uma variável que guarda um endereço de memória onde há umint. *pé a operação de desreferenciar: acessar o inteiro que está no endereço guardado emp.- Antes de usar
*p(ler ou escrever),pdeve conter um endereço válido (por exemplo, o endereço de uma variável existente, como&a). Sepnão foi inicializado, ele contém “lixo” — um endereço qualquer — e usar*pleva a comportamento indefinido (pode travar o programa, sobrescrever memória, etc.).
Passo 4
Identificação precisa do erro no código
- A linha
int *temp;declaratempcomo um ponteiro paraint, mas não inicializa esse ponteiro.temppassa a conter um endereço indeterminado. - Em seguida o código faz
*temp = *i;. Isso tenta escrever no endereço armazenado emtemp. Comotempnão foi inicializado, isso escreve em um endereço arbitrário: comportamento indefinido (possível segmentation fault ou corrupção de memória). - Portanto o problema é que está sendo desreferenciado um ponteiro não inicializado.
Passo 5
Como consertar (solução típica e explicação passo a passo)
- O objetivo é guardar temporariamente o valor inteiro apontado por
i. Para isso não é preciso um ponteiro; precisa-se de uminttemporário que guarde o valor. - Correção correta:
void troca (int *i, int *j) {
int temp; // temp guarda o valor inteiro, não um endereço
temp = *i; // temp recebe o valor apontado por i
*i = *j; // posição de i recebe o valor apontado por j
*j = temp; // posição de j recebe o valor guardado em temp
}
Explicando linha a linha com exemplo numérico:
- Suponha
a = 3em endereço0x100eb = 5em endereço0x200,i = &a,j = &b. int temp;cria uma variáveltemplocal na pilha.temp = *i;lê*i(valor3) e armazena emtemp(agoratemp == 3).*i = *j;lê*j(valor5) e escreve em*i(agoraa == 5).*j = temp;escrevetemp(que é3) em*j(agorab == 3).- Resultado:
a == 5eb == 3, troca feita corretamente.
Passo 6
Outra possibilidade (trocar os ponteiros em vez dos valores)
- Se a intenção fosse trocar os próprios ponteiros (ou seja, fazer
iapontar para o quejapontava e vice-versa), a assinatura da função precisa receber ponteiros para ponteiros:
void troca_ptrs(int **pi, int **pj) {
int *temp;
temp = *pi;
*pi = *pj;
*pj = temp;
}
- Aqui
piepjsão endereços de variáveis do tipoint *, então*pié umint *. Esse código troca endereços; não confundir com trocar os valores apontados.
Passo 7
Resumo de segurança e boas práticas rápidas
- Sempre inicialize ponteiros antes de desreferenciá-los.
- Para trocar valores, use uma variável temporária do tipo do valor (aqui
int temp). - Verifique se os ponteiros de entrada não são NULL (opcional, dependendo do contrato da função):
if (i == NULL || j == NULL) return;
- Comentários e exemplos ajudam a evitar confusões entre “trocar valores” e “trocar ponteiros”.
Resposta
O problema é que
temp foi declarado como int *temp; e nunca inicializado, sendo depois desreferenciado com *temp — isso causa comportamento indefinido. A correção usual é declarar int temp; e usar temp = *i; *i = *j; *j = temp;.