Programação I Ponteiros e alocação dinâmica de memória Prof. Carlos Alberto carlos.batista@facape.br carlos36_batista@yahoo.com.br
Ponteiros O ponteiro é um tipo de dado como int, char ou float; Variáveis do tipo ponteiro são destinadas a guardar e manipular endereços de memória; Por meio do endereço pode-se acessar a informação, dizendo que a variável ponteiro aponta para uma posição de memória.
Ponteiros Operador &: operador unário que devolve o endereço na memória de seu operando. Exemplo: ptr = &cont; Guarda o endereço na memória da variável cont em ptr; Esse endereço é a posição interna da variável na memória do computador e não tem nenhuma relação com o valor de cont. O operador & tem como significado o endereço de.
Ponteiros Operador *: operador unário que devolve o valor da variável localizada no endereço que o segue. Por exemplo, se ptr contém o endereço da variável cont: q = *ptr; coloca o valor de cont em q. O operador * tem como significado no endereço de.
Ponteiros A declaração de uma variável ponteiro é dada pela colocação de um asterisco (*) na frente de uma variável de qualquer tipo: Exemplo: int *ptr; float *q Na linguagem C, é possível definir ponteiros para os tipos básicos ou estruturas.
Ponteiros A definição de um ponteiro não reserva espaço de memória para o seu valor e sim para o seu conteúdo. Antes de utilizar um ponteiro, o mesmo deve ser inicializado. Deve ser colocado um endereço de memória válido para ser acessado posteriormente.
Ponteiros Um ponteiro pode ser utilizado de duas maneiras distintas: Trabalhar com o endereço armazenado no ponteiro; Trabalhar com a área de memória apontada pelo ponteiro. Para trabalhar com o endereço armazenado no ponteiro, utiliza-se o seu nome sem o asterisco na frente. Assim qualquer operação realizada será feita no endereço do ponteiro.
Ponteiros Para trabalhar com a memória apontada pelo ponteiro, alterando ou acessando este valor deve-se colocar um asterisco antes do nome do ponteiro. Assim, qualquer operação realizada será feita no endereço de memória apontado pelo ponteiro.
Ponteiros Exemplo
Ponteiros Maior problema em relação ao ponteiro Entender quando se está trabalhando com o seu valor, ou seja, o endereço; Entender quando se está trabalhando com a informação apontada por ele.
Ponteiros Aritmética de ponteiros É possível realizar operações de soma e subtração com variáveis do tipo ponteiro; A quantidade de endereços de memória relativos ao tipo do ponteiro será somada ou subtraída no ponteiro. Exemplo: um ponteiro para int ocupa 4 bytes, uma operação de soma acrescentará 4 posições na memória;
Ponteiros Exemplo
Ponteiros Vetores como ponteiros em C Vetores são ponteiros com alocação estática de memória; Todo vetor na linguagem C é um ponteiro; Através da aritmética de ponteiros é possível acessar os índices do vetor; Formas para se obter o endereço (ponteiro) do início de um vetor: &vet[0]; vet;
Ponteiros Exemplo
Alocação de memória Alocação estática Ocorre em tempo de compilação; No momento em que se define uma variável ou estrutura é necessário definir seu tipo e tamanho; A memória alocada fica disponível até o término do programa (rotina ou função).
Alocação de memória Alocação dinâmica Ocorre em tempo de execução; As variáveis e estruturas são declaradas sem a necessidade de se definir seu tamanho; Durante a execução do programa a memória será reservada e no momento em que não for mais necessária, deve ser liberada.
Alocação de memória A alocação dinâmica é feita com o auxílio de comandos ou funções que permitem reservar e/ou liberar memória. Na linguagem C, a alocação dinâmica de memória pode ser realizada com apenas quatro chamadas a funções: malloc calloc realloc free
Alocação de memória Função malloc Permite a alocação de uma nova área de memória; Parâmetro: quantidade de bytes para alocação. Retorna, se existir memória suficiente, um endereço que para uma variável do tipo ponteiro. Retorna um ponteiro para o tipo void, deve-se utilizar o typecast, transformando este endereço para o tipo de ponteiro desejado.
Alocação de memória Exemplo da função malloc
Alocação de memória Função calloc Tem a mesma funcionalidade de malloc; Parâmetros: a quantidade de posições a serem alocadas e o tamanho do tipo de dado; Além de alocar o espaço, também inicializa o mesmo com zeros.
Alocação de memória Exemplo da função calloc
Alocação de memória Função realloc Permite que uma área previamente alocada seja aumentada ou diminuída; Parâmetro: o ponteiro retornado pelo malloc e a indicação do novo tamanho; O novo tamanho pode ser maior ou menor que o original;
Alocação de memória Função realloc A realocação de memória pode resultar na troca de blocos na memória. Um ponteiro para o bloco é devolvido porque realloc() pode precisar mover o bloco para aumentar seu tamanho. Se isso ocorrer, o conteúdo do bloco antigo é copiado para o novo bloco, e nenhuma informação é perdida.
Alocação de memória Exemplo da função realloc
Alocação de memória Função free Libera uma área alocada previamente com a função malloc, calloc ou realloc; Parâmetro: o endereço que se deseja liberar; Quando alocamos memória dinamicamente é necessário que nós a liberemos quando ela não for mais necessária.
Alocação de memória Exemplo da função free
Alocação de arrays Para armazenar um array o compilador C calcula o tamanho, em bytes, necessário e reserva posições sequenciais na memória Note que isso é muito parecido com alocação dinâmica Existe uma ligação muito forte entre ponteiros e arrays. O nome do array é apenas um ponteiro que aponta para o primeiro elemento do array.
Alocação de arrays Ao alocarmos memória estamos, na verdade, alocando um array. p 0 1... 99
Alocação de arrays Note, no entanto, que o array alocado possui apenas uma dimensão Para liberá-lo da memória, basta chamar a função free() ao final do programa:
Alocação de arrays Para alocarmos arrays com mais de uma dimensão, utilizamos o conceito de ponteiro para ponteiro. Ex.: char ***p3; Para cada nível do ponteiro, fazemos a alocação de uma dimensão do array.
Alocação de arrays Conceito de ponteiro para ponteiro : Memória posição variável conteúdo 119 120 char ***p3 122 121 122 char **p2 124 123 124 char *p1 126 125 126 char letra a 127
Alocação de arrays Em um ponteiro para ponteiro, cada nível do ponteiro permite criar uma nova dimensão no array. Memória posição variável conteúdo 119 int **p 120 120 p[0] 123 121 p[1] 126 122 123 p[0][0] 69 124 p[0][1] 74 125 126 p[1][0] 14 127 p[1][1] 31 128
Alocação de arrays Em um ponteiro para ponteiro, cada nível do ponteiro permite criar uma nova dimensão no array. 1º malloc: cria as linhas 2º malloc: cria as colunas int **p; int **p; int* int* int* int* int int int int int int int int int* int* int int int int int* int* int int int int
Alocação de arrays Diferente dos arrays de uma dimensão, para liberar um array com mais de uma dimensão da memória, é preciso liberar a memória alocada em cada uma de suas dimensões, na ordem inversa da que foi alocada
Alocação de arrays
Referências BACKES, André. Linguagem C: completa e descomplicada. Editora Campus/Elsevier, 2012. LAUREANO, Marcos. Estrutura de Dados com Algoritmos e C. Rio de Janeiro: Brasport, 2008.