Retorno de um ponteiro em C

7 respostas
Lenin666

Galera, eu sei q esse forum é de Java, mas eu fui ajudar um camarada do meu trampo com uma coisa e fiquei batendo cabeça com esse problema que eu acho que é simples.

A gente está tentando retornar um ponteiro de inteiros e não estamos conseguindo. Será q alguém pode me dar uma luz do meu problema!?

Segue o código:

#include <stdio.h> 

int *retornaVetor();

int main() {

	int *ptr;
	ptr = retornaVetor();
	
	printf("\n\n");
	
	int i;
	for (i = 0; i < 6; i++) {
		printf("Valor do ponteiro eh: %i \n", *(ptr + i));
	}

	return 0; 
}

int *retornaVetor() {
	int my_array[] = {7,23,17,4,-5,100};
	int *ptr;
	ptr = my_array;
	
	int i;
	printf("\n\n");
	for (i = 0; i < 6; i++) {
		printf("Valor do ponteiro eh: %i \n", *(ptr + i));
	}

	printf("\n\n");
	return ptr;
}

Oque eu fiz:
Na função "retornaVetor" ele imprime certinho o array q eu alimentei, já qndo eu tento imprimir no "main", ele me imprime uns números nada haver apartir do segundo elemento.

Segue o que é impresso:

//Dentro da funcao
Valor do ponteiro eh: 7
Valor do ponteiro eh: 23
Valor do ponteiro eh: 17
Valor do ponteiro eh: 4
Valor do ponteiro eh: -5
Valor do ponteiro eh: 100

//Dentro do main
Valor do ponteiro eh: 7
Valor do ponteiro eh: 3078892
Valor do ponteiro eh: [telefone removido]
Valor do ponteiro eh: 878951363
Valor do ponteiro eh: -2
Valor do ponteiro eh: 3078828

Oque eu estou fazendo de errado?

7 Respostas

J

seu problema é que você não recuperou o apontador(não é ponteiro) usando o operador de endereçamento.

int *retornaVetor() {  
    int my_array[] = {7,23,17,4,-5,100};  
    int *ptr;  
    ptr = my_array;  // aqui deve-se usar o operador de endereço ---> ptr = &my_array;
      
    int i;  
    printf("\n\n");  
    for (i = 0; i < 6; i++) {  
        printf("Valor do ponteiro eh: %i \n", *(ptr + i));   // aqui você precisa incrementar o apontador ptr++(o endereço precisa ser incrementado de acordo com a largura dos dados)
    }  
  
    printf("\n\n");  
    return ptr;  
}

essa sua função não retorna um endereço. Ela retorna o valor do primeiro índice do vetor. Para retornar um apontador você precisa novamente usar o operador &

ViniGodoy

Tópico movido para o fórum de outras linguagens.

Além disso, cuidado ao retornar endereços, pois você deve levar em consideração o escopo das coisas.
Não adianta retornar um endereço de uma variável local, criada no stack, pois ela é automaticamente destruída ao final da função.

Se você quer retornar ponteiros, deve criá-los no heap (usando malloc ou, se estiver no C++, o operador new), ou deve garantir que esse dado não sairá do escopo após a execução da função (um dado global, por exemplo ou, ao receber um ponteiro por parâmetro).

Em C++, uma alternativa mais elegante aos ponteiros é usar referências. Se precisar mesmo de ponteiros, considere o uso de Smart Pointers, pois eles poupam muita dor de cabeça ao gerenciar automaticamente recursos (ou seja, eliminam você de ter que pensar onde dar o delete).

J

Esse código acima está voltando lixo de memória por diversos motivos. A questão do escopo também é uma delas.

Quando a função resolver esse endereço não tem mais nada, ou pior pode estar apontando para qualquer lugar.

ViniGodoy
O código correto seria mais ou menos assim (não estou com o compilador aqui para testar):
#include &lt;stdio.h&gt;   
      
int *retornaVetor();  
      
int main() {  
      
        int *ptr;  
        ptr = retornaVetor();  
          
        printf(&quot;\n\n&quot;);  
          
        int i;  
        for (i = 0; i &lt; 6; i++) {  
            printf(&quot;Valor do ponteiro eh: %i \n&quot;, *(ptr + i));  
        }  

        //Criado com malloc deve ser liberado com free, ou então, é memory leak!
        free(ptr); 
        return 0;   
    }  
      
    int *retornaVetor() {  
        int i;  

        int my_array[] = {7,23,17,4,-5,100};  

        //Reservamos memória para os dados no heap
        int* ptr = malloc(sizeof(int) * 6);                  

        //Copiamos os dados do stack para o heap
        memcpy(ptr, my_array, sizeof(myarray));

        printf(&quot;\n\n&quot;);  
        for (i = 0; i &lt; 6; i++) {  
            printf(&quot;Valor no ponteiro: %i \n&quot;, ptr[i]);  //Notação equivalente a *(ptr + i)
        }  
      
        printf(&quot;\n\n&quot;);  
        return ptr;  
    }
ViniGodoy

juliocbq:
Esse código acima está voltando lixo de memória por diversos motivos. A questão do escopo também é uma delas.

Quando a função resolver esse endereço não tem mais nada, ou pior pode estar apontando para qualquer lugar.

E aí:

(É só substituir o nome Spool32 pelo do seu programa, afinal, acessar uma área de memória que não te pertence é a tal operação ilegal).

J
ViniGodoy:
O código correto seria mais ou menos assim (não estou com o compilador aqui para testar):
#include &lt;stdio.h&gt;   
      
int *retornaVetor();  
      
int main() {  
      
        int *ptr;  
        ptr = retornaVetor();  
          
        printf(&quot;\n\n&quot;);  
          
        int i;  
        for (i = 0; i &lt; 6; i++) {  
            printf(&quot;Valor do ponteiro eh: %i \n&quot;, *(ptr + i));  
        }  
        free(ptr); //Criado com malloc deve ser liberado com free
        return 0;   
    }  
      
    int *retornaVetor() {  
        int my_array[] = {7,23,17,4,-5,100};  
        int* ptr = malloc(sizeof(int) * 6);                  
        int i;  
        memcpy(ptr, my_array, sizeof(myarray));
        printf(&quot;\n\n&quot;);  
        for (i = 0; i &lt; 6; i++) {  
            printf(&quot;Valor no ponteiro: %i \n&quot;, ptr[i]);  //Notação equivalente a *(ptr + i)
        }  
      
        printf(&quot;\n\n&quot;);  
        return ptr;  
    }

No caso aqui para você atribuir o conteúdo do endereço tem que derreferenciar o apontador;

*ptr = retornaVetor();

mas se ele quiser voltar o endereço, no qual é a única vantagem de se usar um apontador como resultado:

int &retornaVetor() {  
//...

}

Dessa maneira você pode usar o código como estava mais acima:

ptr = retornaVetor(); //recebe somente o endereço
Lenin666

Valeu galera!

Criado 20 de março de 2012
Ultima resposta 20 de mar. de 2012
Respostas 7
Participantes 3