Alocação verdadeiramente dinâmica [RESOLVIDO]

1. Alocação verdadeiramente dinâmica [RESOLVIDO]

Matth
MattF

(usa Slackware)

Enviado em 03/06/2015 - 18:46h

Como crio um vetor dinamicamente alocável em c? Não estou falandoo de usar maloc e especificar anteriormente, pedindo ao usuário quantos elementos ele vai colocar. Quero um vetor auto alocável. O usuário vai entrando com valores indetermidamente e o vetor aloca na medida da necessidade e somente da necessidado. Como fazer isso?

Pensei em criar um ponteiro global que aponta para um int o qual é a variável que determina o número de elementos do vetor, dentro da main. O que acham? Poderiam exemplificar?


  


2. MELHOR RESPOSTA

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 03/06/2015 - 19:11h

Seria isto?


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

int main(){

int tamanho = 1, numero, i = 0;
int *p1 = (int *)calloc(tamanho,sizeof(int)), *p2;

if(p1 == NULL){
printf("Erro! Sem memoria disponivel!\n");
return -1;
}


while(1){

printf("Digite um numero: ");
scanf("%d",&numero);

if(numero == -10){
tamanho--;
break;
}

p1[i] = numero;
tamanho++;

p2 = (int *)realloc(p1,tamanho * sizeof(int));
if(p2 == NULL){
printf("Erro! Sem memoria disponivel!\n");
free(p1);
return -1;
}

p1 = p2;

i++;

}

printf("Numeros do Vetor: \n");

for(i = 0;i<tamanho;i++){
printf("%d ",p1[i]);
}


free(p1);
return 0;
}



Qualquer dúvida só postar aqui!

Espero ter ajudado

Se ajudei, marque o tópico como resolvido e clique em melhor resposta!

[]'s

T+

--

Programador encontrado morto na banheira cinco dias após ter sido dado como desaparecido. Junto a ele foi encontrado um shampoo com as seguintes instruções:

LAVAR;
ENXAGUAR;
REPETIR;



3. Re: Alocação verdadeiramente dinâmica [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 03/06/2015 - 21:45h

Resolvido?

Espero ter ajudado

[]'s

T+

--

Programador encontrado morto na banheira cinco dias após ter sido dado como desaparecido. Junto a ele foi encontrado um shampoo com as seguintes instruções:

LAVAR;
ENXAGUAR;
REPETIR;




4. Re: Alocação verdadeiramente dinâmica [RESOLVIDO]

Matth
MattF

(usa Slackware)

Enviado em 03/06/2015 - 21:50h


Sim. Mais ou menos o que eu pensei. Só uma dúvida. Qual a diferença entre a calloc e a malloc?


5. Re: Alocação verdadeiramente dinâmica [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 03/06/2015 - 21:53h

MattF escreveu:


Sim. Mais ou menos o que eu pensei. Só uma dúvida. Qual a diferença entre a calloc e a malloc?


Malloc funciona assim "numTamanho 'vezes' sizeof(tipo)" E apenas aloca memoria
Já o Calloc funciona assim "numTamanho 'virgula', sizeof(tipo)" Ele já multiplica e ele inicializa os elementos com o valor zero.

Em suma

Malloc: Apenas reserva um espaço na memória
Calloc: Reserva espaço na memória e inicializa os elementos com 0(zero)

Espero ter ajudado

[]'s

T+

--

Programador encontrado morto na banheira cinco dias após ter sido dado como desaparecido. Junto a ele foi encontrado um shampoo com as seguintes instruções:

LAVAR;
ENXAGUAR;
REPETIR;




6. Re: Alocação verdadeiramente dinâmica

Perfil removido
removido

(usa Nenhuma)

Enviado em 03/06/2015 - 22:20h

malloc() e calloc() na prática fazem a mesma coisa. O que mudam são os parâmetros, a sintaxe. Como se escrevem os parâmetros no programa. Mas melhor explicado na postagem anterior.
Já a função realloc() é a diferente. Ela pode mudar o tamanho da alocação.
--
Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden


7. Re: Alocação verdadeiramente dinâmica

Paulo
paulo1205

(usa Ubuntu)

Enviado em 04/06/2015 - 09:43h

calloc() é equivalente ao seguinte.

void *calloc(size_t n_elems, site_t elem_size){
void *p;
p=malloc(elem_size*n_elems);
if(p)
memset(p, 0, elem_size*n_elems);
return p;
}



Por sua vez, malloc() e free() podem ser implementados usando realloc().

void *malloc(size_t size){
return realloc(NULL, size);
}

void free(void *p){
realloc(p, 0);
}



8. Re: Alocação verdadeiramente dinâmica [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 04/06/2015 - 21:29h

paulo1205 escreveu:

calloc() é equivalente ao seguinte.

void *calloc(size_t n_elems, site_t elem_size){
void *p;
p=malloc(elem_size*n_elems);
if(p)
memset(p, 0, elem_size*n_elems);
return p;
}



Por sua vez, malloc() e free() podem ser implementados usando realloc().

[code]void *malloc(size_t size){
return realloc(NULL, size);
}

void free(void *p){
realloc(p, 0);
} [/quote]

Mas o sistema operacional não segura um número de posição de memória se não usar free()?

--
Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden


9. Re: Alocação verdadeiramente dinâmica [RESOLVIDO]

Enzo de Brito Ferber
EnzoFerber

(usa FreeBSD)

Enviado em 05/06/2015 - 12:12h

listeiro_037 escreveu:
Mas o sistema operacional não segura um número de posição de memória se não usar free()?


Na verdade:


The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.


De acordo com o manual de realloc(), uma chamada a ela com o tamanho como ZERO é equivalente a chamar free().
Então, na verdade, free() é chamado.

http://linux.die.net/man/3/realloc

Enzo Ferber
[]'s


$ cat codigo.c | indent -kr -i8
$ man indent

"(...)all right-thinking people know that (a) K&R are _right_ and (b) K&R are right." - linux/Documentation/CodingStyle - TORVALDS, Linus.



10. Re: Alocação verdadeiramente dinâmica [RESOLVIDO]

Matth
MattF

(usa Slackware)

Enviado em 05/06/2015 - 16:51h


Obrigado pela ajuda pessoal. O problema é que tenho que fazer um programa com um vetor de estruturas, um tanto quanto complicadinho já que essa estrutura contém tipos e outra estrutura dentro. Esse tal vetor deve possuir a propriedade de realocação. Como isso será muito utilizado durante a execução do programa estou pensando em montar um função para adicionar dados a esse vetor. Esse vetor também deverá ser mostrado em alguma opções do programa então deve ser fácil de manipular.

Estou garrado na parte de definir esse vetor indeterminadamente realocável e de fazer uma função para facilitar isso.


11. Re: Alocação verdadeiramente dinâmica [RESOLVIDO]

Matth
MattF

(usa Slackware)

Enviado em 06/06/2015 - 16:23h


Então gente fiz algum progresso. Consegui fazer tal estrutura que é teoricamente dinamicamente allocável. Mas não funciona. TEnho erros de segmentation fault e acho que não deve ser assim. Ai está:


typedef struct sObjeto(){

char tipo[10], cor[10];
int lados, arestas, faces;
}obj;

typedef struct sConjuntoObj(){

obj lista[100]
char NomeDoConjunto[50]
}cjt;

int memcheck(cjt *p){ /
if(p == NULL){
printf(" Sem memoria !!!!\n ");
exit(0);
}
}

int main(){
int tam=0;
cjt * p1 = (cjt *)calloc(tam,sizeof(cjt)), *p2;
tam++;
p2 = (cjt *)realloc(p1,tam * sizeof(cjt));
memcheck(p2);
p1 = p2;


/*****E agora??***/


}



Como faço para preencher p1 dinamicamente e inderteminadamente com cada um dos campos da estrutura
?


12. Re: Alocação verdadeiramente dinâmica

Paulo
paulo1205

(usa Ubuntu)

Enviado em 07/06/2015 - 07:41h

MattF escreveu:


Então gente fiz algum progresso. Consegui fazer tal estrutura que é teoricamente dinamicamente allocável. Mas não funciona. TEnho erros de segmentation fault e acho que não deve ser assim. Ai está:


typedef struct sObjeto(){


Não tenho ideia de por quê você colocou esses parênteses aí. Tire-os pois, na melhor das hipóteses, eles são inócuos e, na pior, transformam o tipo obj numa outra coisa totalmente diferente de uma struct sObjeto.

    
char tipo[10], cor[10];
int lados, arestas, faces;
}obj;

typedef struct sConjuntoObj(){


Idem.

    
obj lista[100]
char NomeDoConjunto[50]
}cjt;

int memcheck(cjt *p){ /
if(p == NULL){
printf(" Sem memoria !!!!\n ");
exit(0);
}
}


Sobre este pedaço:

- Acho um desperdício ter uma função que é um mero apelido para um if. Seria menos ruim se você ao menos tivesse declarado a função com o atributo inline.

- Por convenção o código de saída zero é usado para indicar que o programa executou com sucesso. Como você está abortando o programa por conta de um erro de alocação de memória, seria mais razoável usar um código de saída diferente de zero (geralmente exit(1) é suficiente).

- memcheck não é um nome muito adequado porque não descreve o que a função realmente faz. Algo como assert_valid_ptr ou abort_if_null seria melhor.


int main(){


Essa declaração não está conforme o padrão do C. Ela deveria ser ou “int main(void)” ou “int main(int argc, char **argv)”. Se for C++, “int main()” é válido, e tem o mesmo sentido que tem a primeira forma em C.

  int tam=0;
cjt * p1 = (cjt *)calloc(tam,sizeof(cjt)), *p2;


Essa atribuição no meio da declaração de múltiplas variáveis fica confusa de ler. Pior ainda porque a atribuição é com uma expressão não-constante, com chamada de função e conversão de tipo. Simplifique isso, separando declaração e atribuição em linhas diferentes ou, pelo menos, movendo a variável que recebe a atribuição durante a declaração para o fim da linha.

Note ainda que, se você estiver usando C, a conversão de tipo é desnecessária e, por isso mesmo, não é vista com muito bons olhos por programadores mais experientes. Se, no entanto, você estiver usando C++, a conversão é necessária, mas os programadores experientes na linguagem não gostam de ver malloc() em vez de new, nem de ver calloc() e realloc() em lugar de std::vector().

Mais uma coisa, por sinal importante: veja o que diz o padrão do C, na seção que fala sobre as funções de alocação dinâmica:

If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.


Uma boa prática, que você deve cultivar desde cedo, é não usar código cujo efeito real você desconhece ou que pode se comportar de modos diferentes dependendo do ambiente em que é implementado. No que diz respeito ao seu código, você deu sorte de não ter usado sua “memcheck()” com o valor inicial de p1, pois poderia ou não abortar o programa antes da realocação que vem logo em seguida.

Aliás, dado que logo em seguida você tem uma realocação de p1, por que usar aquele calloc(), em vez de simplesmente NULL? Melhor ainda: se você sabe que vai crescer depois, por que não começar já com um tamanho não-nulo?

  tam++;    
p2 = (cjt *)realloc(p1,tam * sizeof(cjt));
memcheck(p2);
p1 = p2;


/*****E agora??***/


}



Como faço para preencher p1 dinamicamente e inderteminadamente com cada um dos campos da estrutura
?


Não sei se entendi sua dúvida. O que seria “preencher indeterminadamente”? A que estrutura você se refere, a *p1 ou a cada elemento de p1->lista?



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts