Alocação Dinâmica de Memória Ordenação e Pesquisa de Dados Marco Antonio Montebello Júnior [email protected] Definição • Proporciona um modo de acesso a variáveis sem referenciá-las diretamente, utilizando para isto o endereço da variável. • A declaração “*” indica que uma variável é um ponteiro. • Ps.: O uso descuidado de ponteiros pode levar a sérios bugs e a dores de cabeça terríveis :-). Ponteiros Constantes • Não podem ser alterados e permanecem imutáveis durante a execução do programa. • Ex: – int iNotas[10]; • Para acessa a 1ª. posição do vetor pode-se usar: – iNotas ou &iNotas[0] • 2ª. Posição: – &iNotas[1] • E assim sucessivamente... Criando um Ponteiro • Criar uma variável para armazenar o endereço da variável iVar1, a qual iremos chamar de ipVar1 • Nesse momento a variável ipVar1 não foi inicializada, apenas foi reservado um espaço para ela. Criando um Ponteiro • Devemos armazenar o endereço de iVar1 na variável ipVar1. • Nesse momento podemos dizer que ipVar1 aponta para iVar1 ou é um ponteiro para iVar1 • Ps.: Ponteiro é uma variável que contém o endereço de outra variável. Declaração de Ponteiro • <tipo> * <pnome_variavel>; • <tipo> Tipo da variável para a qual o ponteiro estará apontando (int, float, char, ...) • * Operador de indireção e indica que a variavel é um ponteiro para o <tipo> declarado • <nome_variavel> Nome da variável, seguindo as regras de criação de nomes anteriores Declaração de Ponteiro • <tipo> * <pnome_variavel>; • Antes do nome da variável deve existir o *. • É declarado junto com as outras variáveis • Exemplos – int *ipPonteiro; – float *fpPonteiro; – char *cpPonteiro; Inicializando um Ponteiro int iNum, *ipNum; int iVet[10], &ipVet; int iMat[5][7], &ipMat; //Atribuindo os endereços ipNum =&iNum; ipVet = iVet; //ipVetor = iVetor[0]; ipMat = iMat; //ipMat = iMat[0]; Ponteiros e Strings • Declarando uma mensagem como um ponteiro constante – char cMsg [10] = “Saudacoes”; • Declarando uma mensagem como ponteiro variável – char *cpMsg = “Saudacoes”; Matriz de Ponteiros • Matriz constante char cLista[5][10] = • Matriz variável char *cpLista[5] = {"Katarina", "Diogo", "Gustavo", "Francisco", "Airton"}; {"Katarina", "Diogo", " Gustavo", "Francisco", "Airton"}; Matriz de Ponteiros (1) Matriz de Ponteiros (2) Dicas sobre Ponteiro • Acessar o endereço da variável ponteiro – fpPonteiro – printf(“Endereço %f.”, fpPonteiro); • Acessar o conteúdo da variável ponteiro – *fpPonteiro – printf(“Conteúdo: %f.”, *fpPonteiro); Dicas sobre Ponteiro • Acessar o próximo endereço de um ponteiro – fpVet++; – fpVet = fpVet + n;//n=num de bytes a percorrer – fpVet += n; • Acessar o endereço anterior de um ponteiro – fpVet--; – fpVet = fpVet - n;//n=num de bytes a percorrer – fpVet -= n; Dicas sobre Ponteiro • Operações equivalentes • Valor – fVet[2] == *(fpVet + 2) • Endereço – &fVet[2] == (fpVet + 2) Alocação Dinâmica • Aloca espaço na memória durante a execução do programa (em tempo de execução) • Existem funções para alocar, desalocar, realocar e limpar a memória que foi alocada • Usuar a biblioteca stdlib.h • #include <stdlib.h> Função: Sizeof • Indica o tamanho em bytes de uma variável. • sizeof(<tipo>); • Tipo: char, int, float, ... printf(“Tam. printf(“Tam. printf(“Tam. printf(“Tam. int: float: double: char: %i.”, %i.”, %i.”, %i.”, sizeof(int)); //4 sizeof(float)); //4 sizeof(double));//8 sizeof(char)); //1 bytes bytes bytes byte Heap Área de Alocação Dinâmica • Consiste de toda a memória disponível que não foi usada para outro propósito. • “É o resto da memória” • É possível alocar ou liberar dinamicamente a memória do heap através da funções: – – – – malloc() calloc() realloc() free() Função: Malloc • Aloca a quantidade de bytes desejada pelo usuário. • malloc(<tamanho>); int *ipNum1, *ipNum2; ipNum1 = (int *) malloc(4); //Aloca 4 bytes //5 variáveis inteiras = 5 * 4 = 20 bytes ipNum2 = (int *) malloc(5 * sizeof(int)); Função: Malloc • A expressão (int *) é utilizado pois a função malloc(), retorna um ponteiro para o tipo void, portanto esse ponteiro deve ser moldado para o tipo de dado apropriado. • É um operador unário chamado de operador molde ou cast. Função: Calloc • Aloca memória para um grupo de objetos • calloc(<tamanho>, <tam_obj); int *ipNum1, *ipNum2; ipNum1 = (int *) calloc(2, 4); //Aloca 8 bytes //5 variáveis inteiras = 5 * 4 = 20 bytes ipNum2 = (int *) calloc(5, sizeof(int)); Função: Realloc • Altera o tamanho de um bloco de memória que foi alocado através do malloc() ou do calloc() • realloc(<*ptr>, <tamanho>); int *ipNum1, *ipNum2; ipNum1 = (int *) calloc(2, 4); //Aloca 8 bytes //5 variáveis inteiras = 5 * 4 = 20 bytes ipNum2 = (int *) calloc(5, sizeof(int)); ipNum2 = (int *) realloc(ipNum2, sizeof(int) * 10); Função: Free • Limpa um espaço de memória que foi alocado • free(<*ptr>) int *ipNum1, *ipNum2; ipNum1 = (int *) calloc(2, 4); //Aloca 8 bytes //5 variáveis inteiras = 5 * 4 = 20 bytes ipNum2 = (int *) calloc(5, sizeof(int)); //Liberando a memória alocada para ipNum1 e ipNum2 free(ipNum1); free(ipNum2); Exercício • Alocar espaço para um vetor inteiro com 10 posições. Receber do usuário, os valores do vetor. Mostrar o endereço e o respectivo valor de cada elemento da matriz. Em seguida, alterar esses valores, somando 10 a cada elemento. Mostrar novamente o endereço (que deve ser o mesmo) com o novo valor. Utilizar alocação dinâmica e ponteiros, não declarar vetor. Exercício • Aloque espaço para uma seqüência de 5 números reais. Receba do usuário os valores e imprima-os em ordem inversa. Utilizar alocação dinâmica e ponteiros, não declarar vetor. • Altere o exercício anterior de maneira que o usuário indique a quantidade de elementos que ele deseja alocar.