Duvida: retornar vetor em forma de ponteiro

Prezados, bom dia !

Estou desenvolvendo um trabalho para faculdade e encontrei um problema que não consigo resolver.

Seguinte:

1 - Preciso criar uma função que gere um vetor de N elementos, sendo N dado por size;

2- Criada a função, preciso que esse vetor seja retornado para posteriormente ser trabalhado;

No código abaixo ilustrei que o vetor que vai receber 5 valores (0 a 4) de 10, em todos os índices, porém quando executo o código, somente o valor do primeiro índice é exibido corretamente e os demais são endereços de memoria do computador.

Segue o código de ilustração do meu problema:

#include <stdio.h>
#include <stdlib.h>

int *vet(int size);
int main(){
	
	int *ptr;
	int size = 4;
	
	ptr = vet(size);
	
	for(int i = 0; i <= size; i++){
		printf("\n%d", ptr[i]);
	}
}
int *vet(int size){
	
	int *p;
	
	int vet[size];
	p = vet;
	
	for(int i = 0; i <= size; i++){
		vet[i] = 10;
	}
	
	
	
	return p;
}

O problema é o escopo do seu vetor. Quando você aloca estaticamente um vetor ele tem escopo local, isso é, ele só é válido enquanto você está dentro da função. Quando você sai da função essa área de memória será automaticamente liberada. Nesse caso você tem duas opções:

  • Você aloca o vetor globalmente, ou na função principal, e passa o ponteiro como argumento para a função
  • Você aloca o vetor dinamicamente com calloc(size, sizeof(int)), lembrando de liberar a memória com free() depois de usar os dados
1 curtida

Olá amigo, boa tarde e obrigado pela pronta resposta !

Inda estou com dificuldade, não tenho muita experiencia com alocação em C, mas me corrija se estiver errado:

#include <stdio.h>
#include <stdlib.h>
int *vet(int size);
int main(){
	
	int *ptr;
	int size = 4;
	
	ptr = vet(size);
	
	for(int i = 0; i <= size; i++){
		printf("\n%d", ptr[i]);
	}
}
int *vet(int size){
	
	int *p = (calloc(size, sizeof(int)));
	
	int vet[size];
	
	
	for(int i = 0; i <= size; i++){
		vet[i] = 10;
	}
	
	p = vet;
	
	p.free();
	return p;
}

A alocação tem que ser feita dessa maneira:

    int *vet = calloc(size, sizeof(int));

    //manipula o vetor 

   return vet;

A liberação de memória tem que acontecer fora da função, senão você vai retornar um ponteiro que não aponta para nada.

#include <stdio.h>
#include <stdlib.h>

int* vet(int, int);

int main(int argc, char** argv) {
    int tamanho = 4;
    int valorInicial = 10;
    int* ptr = vet(tamanho, valorInicial);
    for (int i = 0; i < tamanho; i++)
        printf("Valor na posicao %d: %d\n", i, ptr[i]);
    free(ptr);
}

int* vet(int tamanho, int valorInicial) {
    int *ptr = malloc(tamanho * sizeof(int)); // aqui você deve alocar memória na heap, e não na stack, para que ela possa ser acessada em outro escopo
    for (int i = 0; i < tamanho; i++)
        ptr[i] = valorInicial;
    return ptr;
}
2 curtidas

Olá amigos, boa tarde e muito obrigado pelas respostas !

Com o auxilio do colega lvbarbosa consegui fazer meu codigo funcionar alterando a instrução:

int* vet(int tamanho, int valorInicial) {

//int *ptr = malloc(tamanho * sizeof(int));

int *ptr = (int*) malloc(tamanho);

for (int i = 0; i < tamanho; i++){
	ptr[i] = valorInicial;
}
    
return ptr;

}

Obrigado, espero um dia ter conhecimento suficiente para ajudar outros !

A chamada pro malloc não tá certa, cuidado!

O argumento que a função malloc recebe a quantidade de bytes que devem ser alocados. Um int tem geralmente 4 ou 8 bytes, dependendo da arquitetura do computador.

Por isso, você tem que colocar malloc(tamanho * sizeof(int)), pois a função sizeof retorna o tamanho em bytes de um tipo.

Se você quer um vetor de ints com tamanho 10, e um int no teu computador tem o tamanho 8, você precisa alocar 80 bytes para guardar os 10 ints. Sacou? Sem levar em conta o tamanho do int, você está alocanco só 10 bytes! A consequência disso é indeterminada. As vezes vai funcionar, as vezes vai dar segmentation fault.

Opa acho que intendi, alterei o codigo para:

int *ptr = (int*) malloc(tamanho *sizeof(int));

e consegui !

Me corrija se estiver errado, obrigado mesmo !

Tá certo! Você também pode usar a função calloc, como o @rmendes08 citou. É um pouquinho diferente, e pode ser mais eficiente (por uma série de motivos de alocação e como as chamadas de sistema são feitas).

Funciona assim: calloc(tamanho, quantidadeDeBytesDeCadaPosicao)

A chamada seria:

int* vet = calloc(10, sizeof(int));

A diferença principal, sem falar de performance, é que o calloc zera todos os bytes do array. Ou seja, vai vir tudo 0. O malloc não zera, vem do jeito que estava antes. Tem uma série de questões como o sistema operacional aloca memória para o processo, de segurança e tals, mas você pode pensar dessa maneira: o malloc pode realocar alguma memória que teu programa já usou antes e liberou, por isso, pode vir com lixo.

1 curtida

Muito obrigado, fico feliz por ter acertado.

Você recomendaria algum livro ou material a respeito de alocação de memoria ? Creio que é um assunto complexo e de difícil assimilação, porém essencial para o desenvolvimento a baixo nível.

Abraços.

Cara, se você pegar um livro de sistemas operacinais bom, como o do Tanenbaum, você vai aprender bastante sobre como funciona um processo e como ele interage com o kernel através das chamadas de sistema. Porém, eu não acho que isso seja extremamente relevante nesse momento que você está começando, vai ofuscar mais do que ajudar. É só minha opinião, quem sou eu para dizer oq vc deve ou não estudar? Kkkkkk

Com certeza é uma leitura ótima e vai te tornar um programador melhor, mas eu diria para você se concentrar mais nos mecanismos da linguagem. Basta saber que malloc, calloc, e realloc fazem a mágica da alocação pra ti!

Acho que o que você precisa aprender além de como usar as funções, é ponteiros. A forma de gerenciamento de memoria muda de linguagem para linguagem, agora o conceito de ponteiros é algo que existe em todas, sendo que em algumas como C isso é mais explicito e em outras não, mas independente é um conceito fundamental de entender.

Da uma olhada ai e faz os exercícios: https://www.ime.usp.br/~pf/algoritmos/aulas/pont.html

Outro material interessante: https://pt.wikibooks.org/wiki/Programar_em_C/Ponteiros