Documente Academic
Documente Profesional
Documente Cultură
Alocao Dinmica em C
Profa Rosana Braga Adaptado de material preparado pela profa Silvana Maria Affonso de Lara 1 semestre de 2010
1
Roteiro da Aula
Alocao Dinmica de Memria Vetores e alocao dinmica Alocao da memria principal Funes para alocar e liberar memria Alocao dinmica de matrizes
A forma mais simples de estruturarmos um conjunto de dados por meio de vetores Definimos um vetor em C da seguinte forma: int v[10]; Esta declarao diz que v um vetor de inteiros dimensionado com 10 elementos, isto , reservamos um espao de memria contnuo para armazenar 10 valores inteiros. Assim, se cada int ocupa 4 bytes, a declarao reserva um espao de memria de 40 bytes
3
144
Em C, a indexao de um vetor varia de zero a n-1, onde n representa a dimenso do vetor. v[0] acessa o primeiro elemento de v v[1] acessa o segundo elemento de v ... Mas v[10] invade a memria
104
v
4
Observe que passamos para scanf o endereo de cada elemento do vetor ( &v[i] ), pois desejamos que os valores capturados sejam armazenados nos elementos do vetor.
Se v[i] representa o (i+1)-simo elemento do vetor, &v[i] representa o endereo de memria onde esse elemento est armazenado Existe uma associao entre vetores e ponteiros, pois a varivel v , que representa o vetor, uma constante que armazena o endereo inicial do vetor, isto , v , sem indexao, aponta para o primeiro elemento do vetor.
5
Portanto, escrever &v[i] equivalente a escrever (v+i) De maneira anloga, escrever v[i] equivalente a escrever
Passar um vetor para uma funo consiste em passar o endereo da primeira posio do vetor. Se passarmos um valor de endereo, a funo chamada deve ter um parmetro do tipo ponteiro para armazenar este valor. Assim, se passarmos para uma funo um vetor de int , devemos ter um parmetro do tipo int* , capaz de armazenar endereos de inteiros Salientamos que a expresso passar um vetor para uma funo deve ser interpretada como passar o endereo inicial do vetor. Os elementos do vetor no so copiados para a funo, o argumento copiado apenas o endereo do primeiro elemento.
#include <stdio.h> void incr_vetor ( int n, int *v ) { int i; for (i = 0; i < n; i++) A sada do programa 2 4 6 , pois os elementos do vetor sero v[i]++; incrementados dentro da funo. } int main ( void ) { int a[ ] = {1, 3, 5}; incr_vetor(3, a); printf("%d %d %d \n", a[0], a[1], a[2]); return 0; }
8
O espao alocado dinamicamente permanece reservado at que explicitamente seja liberado pelo programa. Por isso, podemos alocar dinamicamente um espao de memria numa funo e acess-lo em outra. A partir do momento que liberarmos o espao, ele estar disponibilizado para outros usos e no podemos mais acess-lo. Se o programa no liberar um espao alocado, este ser automaticamente liberado quando a execuo do programa terminar.
10
Para executar um determinado programa, o S.O. carrega na memria o cdigo do programa, em linguagem de mquina. Alm disso, o S.O. reserva os espaos necessrios para armazenar as variveis globais (e estticas) do programa O restante da memria livre utilizado pelas variveis locais e pelas variveis alocadas dinamicamente.
12
Cada vez que uma funo chamada, o S.O. reserva o espao necessrio para as variveis locais da funo. Este espao pertence pilha de execuo e, quando a funo termina, liberado. A memria no ocupada pela pilha de execuo pode ser requisitada dinamicamente. Se a pilha tentar crescer mais do que o espao disponvel existente, dizemos que ela estourou e o programa abortado com erro.
13
size
/* retorna um ponteiro void para n bytes de memria no iniciados. Se no h memria disponvel malloc retorna NULL */
14
o ponteiro retornado por malloc e calloc deve ser convertido para o tipo de ponteiro que invoca a funo
15
16
sucedida, vet armazenar o endereo inicial de uma rea contnua de memria suficiente para armazenar 10 valores inteiros.
Desta forma, consideramos que um inteiro ocupa 4
bytes. Para ficarmos independentes de compiladores e mquinas, usamos o operador sizeof( ) v = malloc(10*sizeof(int));
17
Podemos tratar o erro na alocao do programa verificando o valor de retorno da funo malloc Ex: imprimindo mensagem e abortando o programa com a funo exit, tambm definida na stdlib.
Int * v; v = (int*) malloc(10*sizeof(int)); if (v==NULL) { printf("Memoria insuficiente.\n"); exit(1); /* aborta o programa e retorna 1 para o sist. operacional */ }
19
Liberao de Memria
int *pi = (int *) malloc (sizeof(int)); /* aloca espao para um inteiro */ int *ai = (int *) calloc (n, sizeof(int)); /* aloca espao para um array de n inteiros */
toda memria no mais utilizada deve ser liberada atravs da funo free():
20
Exerccio 1
Escreva um programa em C que solicita ao usurio um nmero n e ento l um vetor de n notas e calcula a mdia aritmtica.
Usar alocao dinmica do vetor Liberar a memria ao final No limitar o uso de memria
21
A alocao dinmica de memria para matrizes realizada da mesma forma que para vetores, com a diferena que teremos um ponteiro apontando para outro ponteiro que aponta para o valor final, o que denominado indireo mltipla A indireo mltipla pode ser levada a qualquer dimenso desejada.
22
** p0
** p2+1 ** p3+3
Cada linha da matriz representada por um vetor independente. A matriz ento representada por um vetor de vetores, ou vetor de ponteiros, no qual cada elemento armazena o endereo do primeiro elemento de cada linha
v = (float **) calloc (m, sizeof(float *)); if (v == NULL) { printf ("** Erro: Memoria Insuficiente **"); return (NULL); }
25
for ( i = 0; i < m; i++ ) { v[i] = (float*) calloc (n, sizeof(float)); if (v[i] == NULL) { printf ("** Erro: Memoria Insuficiente **"); return (NULL); } } return (v); /* retorna o ponteiro para a matriz */ }
26
28
Exerccio 2
Modificar o programa de alocao dinmica de matrizes dado anteriormente (slides 25 a 28) para que leia aloque dinamicamente duas matrizes de 3 por 4, leia seus elementos e imprima a matriz soma.