Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
comecei a estudar listas hoje e os tutoriais online mandam depois de declarar a seguinte estrutura:
struct node
{
int var;
struct node* next;struct node* ponteiro;
até aí tudo bem, mas então dizem que é preciso faser isso:
ponteiro= (struct node*) malloc(sizeof(struct node));
mas se ele é um ponteiro to tipo struct node, não quer dizer que ele já tem o espaço sizeof(struct node)?
essa malloc seria então inútil e não estaria fazendo nada?
qual a explicação?
não sei se entendi.
se eu declaro ponteiros tipos int, char, float ou qualquer tipo, o ponteiro não tem o espaço de memória pra aquele tipo e portanto eu tenho que reservar esse espaço com a malloc?
entendi correto?
deisa eu ser mais claro. ao fazer:
int* ptr;
este ponteiro não tem o espaço de memoria para inteiros e por isso eu preciso fazer:
ptr=malloc(sizeof(int));
é isso que ocorre?
O ponteiro declarado ocupa 4 bytes em memória. Ele vai armazenar o endereço de memória que ainda precisa ser alocado com malloc.
int * ptr -> reserva um pedaço da memória de tamanho 4bytes (no meu caso) que armazena um endereço de memória (e não o dado real).
malloc(sizeof(int)) -> reserva um espaço "aleatório" em memória do tamanho necessário para armazenar um inteiro (no meu caso, 4 bytes)
Se você não atribuir o resultado do malloc, seu programa terá o que se chama de vazamento de memória (memory leaking).
É bem diferente de int ptr -> aqui você reserva 4 bytes (supondo que esse seja o tamanho do tipo inteiro) e consegue referenciar esse espaço reservado como inteiro, armazenando o dado real ao invés de um endereço de memória "intermediário".
A declaração int ptr é o que se chama,no c99, de variável automática (ela é alocada e liberada automaticamente no início e fim do escopo, respectivamente).
C99
An object has a storage duration that determines its lifetime. There are three storage durations: static, automatic, and allocated. Allocated storage is described in 7.20.3.
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. (...) The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementationdefined: 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.
então, se ao declarar int* ptr eu estou fazendo um ponteiro de 4 bytes, eu não preciso fazer: ptr = malloc(sizeof(int)), (porque eu estaria separando 4 bytes de memória pra um ponteiro que são 4 bytes).
eu não entendo então, porque depois de declarar: struct tipo* ptr
porque eu precisaria fazer: ptr = malloc(sizeof(struct tipo)) como mandam os tutoriais?
me perdoe se eu não fui claro e por te perturbar tanto Isis, é por uma boa causa
Uma coisa é a declaração de int ptr / struct ptr. Outra coisa é a alocação de memória para vc armazenar o objeto real. São duas coisas diferentes e separadas.
Ao declarar o ponteiro você não armazenou nada e nem reservou espaço em memória p/ o dado real.
int main(void) {
int * ptr; // reserva espaço em memória equivalente a 4 bytes p/ armazenar um endereço de memória de um inteiro.
int a = 9; // reserva espaço em memória equivalente a 4 bytes e armazena o número 9. Alocação automática.
ptr = &a; // ptr recebe o endereço no qual o número 9 foi armazenado.
ptr = malloc(sizeof(int)); // ptr recebe um endereço alocado dinamicamente pelo programador e que ainda não tem um valor armazenado.
*ptr = 10; // Armazena no endereço em ptr, vindo do malloc, o número 10.
free(ptr); // libera o endereço de memória alocado via malloc. Como não é alocação automática, o programador [b]deve[/b] fazer isso
return 0;
}
Alocação dinâmica é muito utilizada p/ criar tipos de dados como listas ligadas, árvores, grafos....Coisas que tem o tamanho alterado durante a execução do programa ,já que você não pode alterar um int [] ou struct [] durante a execução.
então quando eu faço:
struct tipo* ptr;
esse ponteiro já contem os bytes necessários para caber uma variável "struct tipo".
logo, eu não preciso usar malloc né?
Não. De novo:você só está declarando uma variável do tipo ponteiro pra struct, que vai armazenar um endereço de memória de uma struct que você ainda vai ter que alocar ou referenciar a partir de uma variável automática.
Ponteiro não armazena o objeto real. Ele armazena um endereço de memória/referência para um objeto em memória.
Leia os comentários do código.
Malloc não precisa ser usado com sizeof necessariamente. É possível passar uma constante, como malloc(5), o que significa que você quer reservar espaço de 5 bytes em memória.
struct node * p apenas declara uma variável, não define/inicializa espaço nenhum em memória. O ponteiro serve apenas para guardar a referência ao espaço de memória reservado pelo malloc em algum canto da RAM. O tamanho da struct (sizeof(struct node)) pode ser diferente do tamanho da variável do tipo ponteiro. Aqui no meu computador
sizeof(struct node) = 8 bytes
sizeof(struct node *) = 4 bytes
Então o tamanho ocupado em memória pela variável do tipo struct node (usada para armazenar o endereço de memória que realmente contém os dados da struct) é 4 bytes. O tamanho da struct em si é 8 bytes (4 do inteiro + 4 do struct node ).
É possível usar void p = malloc(sizeof(struct node)). O problema disso é que você perde a verificação da tipagem, já que o void é genérico..