Ir ao conteúdo
  • Cadastre-se
Josesousa

C Criar vetor dinamicamente, Liberar. Tudo em funções.

Recommended Posts

Bom dia, como vão? (Vou bem)

 

Estou com dificuldades para criar um vetor, dinamicamente no caso, dentro de uma função.

Segue o codigo e apos ele algumas observacoes que percebi.

 

/**Faça uma função que receba um valor n e crie dinamicamente um vetor de n elementos e
retorne um ponteiro. Crie uma função que receba um ponteiro para um vetor e um valor n e
imprima os n elementos desse vetor. Construa também uma função que receba um ponteiro
para um vetor e libere esta área de memória. Ao final, crie uma função principal que leia um
valor n e chame a função criada acima. Depois, a função principal deve ler os n elementos
desse vetor. Então, a função principal deve chamar a função de impressão dos n elementos
do vetor criado e, finalmente, liberar a memória alocada através da função criada para
liberação.*/
#include <stdio.h>
#include <stdlib.h>
main(){
    int n,*vet, i;
    printf("Informe o tamanho do vetor: ");
    scanf("%d", &n);

    int criar(int *vet, int n);
    criar(vet,n);

    printf("\nPreencha o vetor agora.\n");
    for(i=0;i<n;i++){
        printf("Vetor [%d]: ",i);
        scanf("%d", &vet[i]);
    }

    void imprima(int *vet, int n);
    imprima(vet, n);

    void libera(int *vet);
    libera(vet);

    printf("\nO vetor depois de liberar.\n");
    for(i=0;i<n;i++){
        printf("Vetor [%d]: %d\n", i,vet[i]);
    }
}
int criar(int *vet, int n){
        vet =(int *) malloc(n * sizeof(int));
    return *vet;
}
void imprima(int *vet, int n){
    int i;
    printf("\nO vetor ficou da seguinte forma.\n");
    for(i=0;i<n;i++){
        printf("Vetor [%d]: %d\n", i,vet[i]);
    }
}
void libera(int *vet){
        free(vet);
}

 

Pois bem, se na funcao principal eu criar um vetor de forma normal, e não um ponteiro para depois ser criado um vetor dinamicamente, vai funcionar perfeitamente. So que no caso acredito que assim não seja possivel criar de forma dinamica.. A forma abaixo é o vetor criado normalmente e que funciona no exercicio.

main(){
	int n=2, vet[n],i;
....
}

So que depois de char a a função liberar, que faz uso do free(), continua a mostrar os mesmos valores, como se nao ouvesse sido liberada. E na primeira forma (a que nao da certo) eu não consigo nem ler o vetor na funcão principal.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Josesousa Olá. Para q o exercício fique mais didático, seu código poderia ser feito assim (sem o uso de função):

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

int main(){

    int n, *vet = NULL, i; // iniciliza o ponteiro fazendo ele apontar p NULL (lugar nenhum)

    printf("Informe o tamanho do vetor: ");
    scanf("%d", &n);

    vet = malloc(n * sizeof(int));

    printf("\nPreencha o vetor agora.\n");

    for(i = 0; i < n; i++){
        printf("Vetor [%d]: ",i);
        scanf("%d", &vet[i]);
    }

    printf("\nVetor:\n\n");
    for (i = 0; i < n; i++) {
        printf("%d ", vet[i]);
    }

    free(vet); // libera a memória alocada

    printf("\n\nO vetor depois de liberar.\n");

    for(i = 0; i < n; i++){
        printf("Vetor [%d]: %d\n", i,vet[i]);
    }

    vet = NULL; // faz o ponteiro voltar a apontar p NULL

    return 0;
}

Depois q entender bem o q está sendo feito nesse código, aí pode fazer uso de funções

adicionado 25 minutos depois

@Josesousa Já se quer mesmo fazer uso de funções, de acordo com o enunciado do exercício, seu código poderia ficar assim:

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

// Protótipo das funções
int *aloca_vetor(int *, int);
void libera_vetor(int *);
void imprime_vetot(int *, int);

int main(){

    int n, *vet = NULL, i;

    printf("Informe o tamanho do vetor: ");
    scanf("%d", &n);

    vet = aloca_vetor(vet, n);

    printf("\nPreencha o vetor agora.\n");

    for(i = 0; i < n; i++){
        printf("Vetor [%d]: ",i);
        scanf("%d", &vet[i]);
    }

    imprime_vetor(vet, n);

    libera_vetor(vet);

    printf("\n\nO vetor depois de liberar.\n");
    for(i = 0; i < n; i++){
        printf("Vetor [%d]: %d\n", i,vet[i]);
    }

    vet = NULL;

    return 0;
}

int *aloca_vetor(int *vet, int n) {
    vet = malloc(n * sizeof(int));
    return vet;
}

void libera_vetor(int *vet) {
    free(vet);
}

void imprime_vetot(int *vet, int n) {

    int i;

    printf("\nVetor:\n\n");
    for (i = 0; i < n; i++) {
        printf("%d ", vet[i]);
    }
}

Vê se deu p entender bem o código

qualquer dúvida é só perguntar

Editado por giu_d
  • Curtir 3

Compartilhar este post


Link para o post
Compartilhar em outros sites

Segundo o enunciado a função que aloca recebe apenas um valor n, logo não precisa do ponteiro vet como parâmetro da função:

int *aloca_vetor(int n) {
    int *vet;
    vet = malloc(n * sizeof *vet);
    return vet;
}

 

(Também notei que o enunciado não especifica que o tipo dos elementos alocados é int, isso significa que o tipo fica a seu critério?)

  • Curtir 3

Compartilhar este post


Link para o post
Compartilhar em outros sites

@isrnick Exato! Bem observado. Não se faz mesmo necessário passar o vetor como parâmetro da função

Mas gostaria de frisar q, ao criar um ponteiro do tipo int * como você fez acima, té por ser uma boa prática de programação, é recomendável inicializar esse ponteiro fazendo o mesmo apontar p NULL (lugar nenhum):

int *vet = NULL

Com isso você deixa d fazer com q o ponteiro seja um "ponteiro selvagem", q pode apontar p qualquer região da memória, inclusive uma região q pode estar sendo usada por outro programa

Se estou errado me corrija :thumbsup:

Editado por giu_d
  • Curtir 3

Compartilhar este post


Link para o post
Compartilhar em outros sites

@giu_d Correto, e também deveria checar se houve sucesso ao alocar memória:

int *aloca_vetor(int n) {
    int *vet = NULL;
    vet = malloc(n * sizeof *vet);
    if (vet == NULL){
        printf("\nERRO: Falhou ao tentar alocar memoria! Nao ha memoria livre suficiente!\n");
        exit(EXIT_FAILURE);
    }
    return vet;
}
  • Curtir 3

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 horas atrás, giu_d disse:

int *aloca_vetor(int *, int);

void libera_vetor(int *);

void imprime_vetot(int *, int);

@giu_d Porque que nessa parte não está igual como na função, com os nomes das variaves?

 

Toda vez que for criar uma funcao que aloca dinamicamente uma vetor ela tem que ter o '*' nela? 

adicionado 4 minutos depois

Pensei tambem que quando alocava uma variavel seguia esse padrão:

 variavel = (tipo *) malloc (tamanho * sizeof (tipo);

No caso você não usou o primeiro parenteses acima

adicionado 15 minutos depois

 

 

@isrnick Porque que multiplica pelo vetor direto (logo apos o sizeof), e não o tipo? (esse retorno eu teria que atribuir a outra variavel para poder usar,ne)

1 hora atrás, isrnick disse:

int *aloca_vetor(int n) {

    int *vet;

    vet = malloc(n * sizeof *vet);   

return vet;  

}

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Josesousa Olá. Quanto a essa pergunta:

3 horas atrás, Josesousa disse:
6 horas atrás, giu_d disse:

int *aloca_vetor(int *, int);

void libera_vetor(int *);

void imprime_vetot(int *, int);

@giu_d Porque que nessa parte não está igual como na função, com os nomes das variaves?

 

Quando se faz a declaração de uma função, q é chamada de protótipo de uma função, o q é necessário informar é o tipo de retorno da função, o nome da função, o número e os tipos dos parâmetros (argumentos).

O propósito principal de escritas de protótipos das funções em C é fornecer ao compilador as informações necessárias sobre uma função.

Sem o protótipo das funções, o compilador não tem como verificar e checar se há erros em seu uso.

Quanto a colocar ou não o nome dos parâmetros não é obrigatório. Informando apenas o tipo de cada parâmetro já é o suficiente. 

Claro q se você preferir, ao fazer a declaração d uma função (protótipo de uma função) você pode sem problemas nenhum informar o nome dos parâmetros também. Mas, para o compilador, sabendo apenas o número de parâmetros e o tipo de cada parâmetro já é o suficiente.

O protótipo da função aloca poderia ser escrito assim:

int *aloca_vetor(int *vet, int n);

Mas não é necessário informar o nome dos parâmetros (variáveis) nesse caso

 

4 horas atrás, Josesousa disse:

Toda vez que for criar uma funcao que aloca dinamicamente uma vetor ela tem que ter o '*' nela?

 

Esse asterisco creio q você está se referindo a isso: int * aloca_vetor(int *, int);

De acordo com o enunciado é preciso q essa função retorne um ponteiro. Logo, com esse asterisco, eu estou definindo q o tipo de retorno da função é int *, pois nessa função eu retorno um ponteiro do tipo int *, que é exatamente o q pede o enunciado

 

quanto a essa dúvida:

4 horas atrás, Josesousa disse:

variavel = (tipo *) malloc (tamanho * sizeof (tipo);

na verdade ao fazer alocação de memória com o malloc, não se faz esse casting q você mostrou dessa forma: (tipo *).

Isso porque é algo desnecessário e pode te induzir ao erro.

Quando eu faço algo assim:

vet = aloca_vetor(vet, n);

O q acontece é uma conversão implícita para o tipo do ponteiro, q, nesse exemplo, é int *

 

Rapaz, me colocou num aperto com essas perguntas. rs...

Se deu para entender maravilha! Se tiver dúvida é só perguntar, ok?

 

  • Curtir 2
  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
6 horas atrás, giu_d disse:

De acordo com o enunciado é preciso q essa função retorne um ponteiro. Logo, com esse asterisco, eu estou definindo q o tipo de retorno da função é int *, pois nessa função eu retorno um ponteiro do tipo int *, que é exatamente o q pede o enunciado

Eu tinha para mim que vetor sempre era um ponteiro, então sempre ia retornar ponteiro.

( Mas nem passou na minha cabeca isso de colocar a função como int *, interessante isso, pensave que na ora do return que eu mudaria a forma que seria retornado, colocando * ou & , ,,,,,cada coisa.)

 

6 horas atrás, giu_d disse:

Mas, para o compilador, sabendo apenas o número de parâmetros e o tipo de cada parâmetro já é o suficiente

Quando estava aprendendo sobre funcao, no inicio eu fazia isso. Alias, quase isso, pois eu colocava so o nome da funcao e deixava o paranteses sem nada . kkkk (mas nunca deu problemas em rodar os exercicios, hoje sei que esta errado)

 

6 horas atrás, giu_d disse:

Rapaz, me colocou num aperto com essas perguntas. rs...

Foi mal o tanto de pergunta ai, é que nao sabia mesmo. rsrsrs

 

Muito obrigado, @giu_d . Esta me ajudando muito .:D 

  • Curtir 1
  • Obrigado 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Josesousa

1 hora atrás, Josesousa disse:
8 horas atrás, giu_d disse:

Rapaz, me colocou num aperto com essas perguntas. rs...

Foi mal o tanto de pergunta ai, é que nao sabia mesmo. rsrsrs

 

Cara... eu gosto quando alguém faz perguntas mesmo. Isso deixa claro q essa pessoa quer mesmo aprender. Tal como no seu caso

Fique a vontade p perguntar o q quiser e na hora q quiser! :thumbsup:

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
Em 15/08/2018 às 12:41, Josesousa disse:

 

@isrnick Porque que multiplica pelo vetor direto (logo apos o sizeof), e não o tipo? (esse retorno eu teria que atribuir a outra variavel para poder usar,ne)

Em 15/08/2018 às 10:53, isrnick disse:

int *aloca_vetor(int n) {

    int *vet;

    vet = malloc(n * sizeof *vet);   

return vet;  

}

 

Não está multiplicando por um vetor, está multiplicando pelo tamanho da variável *vet, ou seja em sizeof *vet esse asterisco não é uma multiplicação, sizeof é uma palavra chave reservada da linguagem, e serve para obter o tamanho em bytes de algo, nesse caso como *vet é do tipo int o resultado é o tamanho de int (normalmente int tem 4 bytes).

 

A vantagem de fazer assim, ao invés de usar sizeof(int), é que não precisa checar qual o tipo do ponteiro vet, então se mudar o tipo de vet, (por exemplo declarar a variável como double *vet;) o malloc não precisa ser alterado, pois vai funcionar corretamente usando o tamanho certo.

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×