Académique Documents
Professionnel Documents
Culture Documents
Referncias Bsicas
Gries, D., The Science of Programming, Springer-Verlag, New York, 1985. Hehl, M.E., Linguagem de Programao Estruturada FORTRAN 77, McGraw-Hill, 1986. Arakaki, R. et. alli., Fundamentos de Programao em C, Livros Tcnicos e Cientficos. Kernighan, B.W.; Ritchie, D.M., The C Programming Language, Prentice-Hall, Second Edition, 1988. Savitch, W.J., Pascal: An Introduction of the Art and Science of Programming, The Benjamin / Cummings Publishing Company, 1984.
Introduo
Principal desafio: Como escrever eficientemente programas grandes? Um enfoque: 1. Pegue uma tarefa longa, quebre em pedaos (blocos) menores. 2. Repita 1. at que os pedaos sejam unidades inteligveis e fceis de serem manipuladas. Programa bem projetado: Unidades pequenas, independentes e bem documentadas. Programao estruturada: Formaliza a idia de dividir em blocos. Isto fora o programador a saber exatamente o estado do programa antes e depois de cada bloco e evita o chamado cdigo espaguete, onde no se tem noo em que estgio da execuo o programa se encontra em uma determinada instruo. Diagrama de blocos: Utilizado para mostrar graficamente o fluxo de controle de um programa. Adotado a notao de diagrama de blocos N-S (Nassi-Schneiderman) [Arakaki, Apndice B]. Comentrios em C:
/* Este um comentrio no meio de um cdigo em C */
Programao seqencial
O fluxo de controle de um programa estruturado feito de bloco em bloco, seqencialmente, onde cada bloco pode ser: uma instruo; um conjunto de instrues; um aninhamento de outros blocos; uma rotina (funo); um programa. Diagrama N-S: Bloco 1 Bloco 2 Bloco n Para se poder garantir que o fluxo de controle feito de forma seqencial, associado a cada bloco existe uma assero de pr-condio e uma assero de ps-condio:
/* pre: assero de pr-condio */ /* pos: assero de ps-condio */
Uma assero um comentrio que afirma alguma coisa que o programador espera ser verdadeira quando a execuo do programa atinge a assero. Exemplo:
/* pre: x + 1 > 0 */ x = x + 1; /* pos: x > 0 */
Uma tripla pre-bloco-pos diz que se a assero pre verdadeira antes da execuo do bloco, ento a assero pos verdadeira aps a execuo. A tripla no diz absolutamente coisa alguma a respeito da execuo do bloco quando pre falsa.
Exemplo em C:
/* Armazene em z o max(a,b) */ if( a > b ) { z = a; } else { z = b; } /* Alternativa em C */ z = ( a > b ) ? a : b;
Estruturas de controle
Na programao estruturada, a estruturao est baseada em um pequeno nmero de estruturas de controle: controle seqencial; controle de deciso; controle de seleo mltipla; controle de iterao do tipo enquanto-faa; controle de iterao do tipo repita-enquanto. Pode-se estabelecer o Princpio da Programao Estruturada (Hehl, 1986): Qualquer algoritmo pode ser escrito combinando-se blocos formados pelas estruturas de controle acima.
Pseudo-cdigo:
if( exp ) { Bloco A }
Controle de deciso
Diagrama N-S: Condio? Sim Bloco A No Bloco B
Pseudo-cdigo:
/* exp: expresso booleana */ if( exp ) { Bloco A } else { Bloco B }
Expresso booleana: Nos exemplos acima exp uma expresso lgica relacional (expresso booleana) que contem: operadores relacionais: maior que maior ou igual a menor que menor ou igual a igual a diferente de operadores lgicos: conjuno (AND) disjuno (OR) negao (NOT) Expresses booleanas em C: operadores relacionais: > (maior que) >= (maior ou igual a) < (menor que) <= (menor ou igual a) == (igual a) != (diferente de) operadores lgicos: && (conjuno) || (disjuno) ! (negao)
A instruo break necessria ao final de cada opo pois seno as instrues do bloco seguinte (pertencentes opo seguinte) seriam executadas. Isto feito de forma a permitir que dois ou mais valores diferentes da varivel de seleo fiquem associados a um mesmo bloco. Isto mostrado abaixo:
switch( elemento ) { case a: case b: case c: Bloco A break; default: Bloco N break; }
Bloco N
A estrutura ifelse ifelse tambm pode ser representada no diagrama N-S como mostrado abaixo: Sim Condio? exp1 Sim Condio? exp2 No No Condio? Sim exp3 No
Um exemplo do loop while mostrado na implementao da funo binary que acha a posio de um nmero inteiro x em um vetor v[0..n-1] ordenado seqencialmente (veja Kernighan & Ritchie, 1988):
int binary( int x, int v[], int n ) { int low, high, mid; low = 0; high = n 1; while( low <= high ) { mid = (low + high) / 2; if( x < v[mid] ) high = mid 1; else if( x > v[mid] ) low = mid + 1; else /* found match */ return( mid ); } return( 1 ); }
Diagrama N-S do loop do while: Bloco Enquanto( exp ) Tanto o loop while quanto o loop do while terminam quando suas expresses booleanas so falsas. Uma diferena importante entre os dois tipos de loops que no loop while a expresso booleana verificada primeiro e se o seu valor for falso, o corpo do loop nunca executado; no loop do tipo do while, o corpo do loop sempre executado pelo menos uma vez pois a expresso booleana verificada no final do loop. Implementao de laos em C:
/* Enquanto ... faa ... */ while( exp ) { Bloco } /* Repita ... enquanto ... */ do { Bloco } while( exp );
A linguagem C tambm apresenta um outro tipo de lao enquanto ... faca .... o loop do tipo for, cujo diagrama N-S e instrues so mostrados a seguir: Para <inic>; Enquanto <exp>; Passo <reinic> Bloco
for( inic; exp; reinic ) { Bloco }
Onde inic um bloco de instrues de inicializao do lao, exp a expresso booleana para repetio da iterao e reinic um bloco de instrues para reinicializao da iterao. O lao for acima inteiramente anlogo ao lao while abaixo:
init; while( exp ) { Bloco reinic; }
interassante observar que na linguagem Pascal o loop do while substituido pelo loop repeat until que termina quando a expresso booleana verdadeira.
A utilizao mais freqente do loop for para fazer algum tipo de iterao com vetores, tal como inicializar com zeros o vetor de inteiros v[0..n-1]:
void init_vector( int v[], int n ) { int i; for( i=0; i<n; i++ ) v[i] = 0; }
Desenvolvimento de Loops
Dentro da programao estruturada foi caracterizado a existncia de asseres que podem ser feitas sobre o estado do programa antes de depois de cada bloco. Esta asseres so uma garantia que o programador tem sobre o comportamento do programa durante a sua execuo. Dada a importncia do lao em programao, interessante que se possa estabelecer outras asseres a respeito do seu comportamento de forma a se ter uma gantantia de que as iteraes de um lao iro terminar, convergindo para o resultado desejado. Considere o loop a seguir, que armazena na varivel s a soma dos elementos do vetor b[0..n1]. O loop est comentado de forma que a assero inv descreve os valores de s e i antes (e depois) de cada iterao.
/* pre: * b[0..n1], onde n 0; * (n = 0 => b[0..1], vetor vazio) */ i = 0; s = 0; /* inv: * i = 0; * s a soma de b[0..1]; * n iteraes a fazer */ while( i != n ) { /* inv: * 0 i < n; * s a soma de b[0..i1]; * ni iteraes a fazer */ s += b[i++]; } /* inv = pos: * i = n; * s a soma de b[0..n1]; * 0 iteraes a fazer */
A instruo break em C causa a terminao do comando while, do while, for ou switch que envolve o break e que o mais interno. O fluxo passa para a instruo seguinte ao comando terminado. A instruo continue em C faz com que o fluxo de um lao (while, do while ou for) passe para o fim do lao de forma que a expresso booleana para repetio seja imediatamente verificada. Os comandos continue e goto podem ser entendidos pelos dois loops inteiramente equivalentes mostrados a seguir:
while( exp ) { Bloco A continue; Bloco B } | while( exp ) | { | Bloco A | goto CONTIN; | Bloco B | CONTIN: | } /* CONTIN um rtulo */
A instruo return interrompe o fluxo pois causa o retorno imediato para o funo que chamou a funo ativa.
Algumas observaes podem ser feitas a respeito do loop comentado: Se n = 0 (vetor vazio), ento a soma final s = 0. Tem-se sempre ni iteraes a fazer: ni decresce a medida que o loop executado; se existe alguma iterao a fazer, ento ni > 0;
ni chamado de funo teto (ft) do loop pois estabelece um valor mximo (um teto) para o nmero de iteraes que ainda devem ser feitas durante a execuo do loop. Savitch (1984) chama esta funo de variant expression. Se inv uma assero verdadeira e ft=0; ento a assero de ps-condio pos tambm verdadeira.
/* pre: ... */ initS; /* inv: ... */ /* ft: ... */ while( exp ) { S; } /* pos: ... */
Exemplos de desenvolvimento de loops: 1. Este programa acha a primeira posio i do valor x no vetor b[0..n1], dado que x est em b[]:
/* pre: x b[0..n1] */ i = 0; /* inv: x b[0..i1] * x b[i..n1] */ /* ft: n i */ while( b[i] != x ) i++; /* pos: b[i] = x */
A assero inv chamada de invariante do loop porque ela invariavelmente verdadeira antes e depois de cada iterao. A funo teto ft uma garantia de que o loop ir terminar. Com base neste exemplo, pode-se descrever um mtodo geral para o entendimento de um loop genrico, tal como o mostrado a seguir, e para demonstrar que ele ir terminar:
/* pre: ... */ initS; /* instrues para iniciar */ /* inv: ... */ while( exp ) { /* inv: ... */ S; /* instrues do loop */ } /* inv: ... */ /* pos: ... */
Mtodo: 1. Ache um invariante inv. 2. Mostre que initS; estabelece o invariante, isto , comprove a tripla:
/* pre: */ initS; /* inv: */
2. Este segundo programa calcula quociente q e o resto r quando x dividido por y. Para x>y>0, q e r so definidos por:
x = q*y + r
0 r < q
5. Demonstre que o loop termina, isto , ache uma funo teto ft tal que: ft decresce em cada iterao; /* inv: AND exp */ ft > 0. Um loop fica convenientemente comentado tal como mostrado abaixo. Este formato deixa claro o que so o invariante e a funo teto, sendo que eles s precisam ser escritos uma s vez:
y > 0 x; q*y + r r
q )
q*y + r r < q
3. O terceiro programa um vetor b[0..n1], dado que contem nmeros 1s, 2s e 3s, de tal forma que os 1s precedam os 2s que por sua vez precedam os 3s:
/* pre:
0 n 1's ? 2's ? 3's
Exerccios propostos
1. Indique se as seguintes triplas de instrues so falsas ou verdadeiras. Em caso de falsa, justifique. Todas as variveis so inteiras. (a) /* i par */
i = i/2; /* i par */
*/ f = 0; h = 0; /* inv:
0 f 1's 2's
k = n 1;
h ? k 3's n
(b) /* i negativo */
i = i*i; /* i no-negativo */
*/ /* ft: k h */ while( h <= k ) switch( b[h] ) { case 1: t = b[h]; b[h] = b[f]; b[f] = t; f++; h++; break; case 2: h++; break; case 3: t = b[h]; b[h] = b[k]; b[k] = t; k ; break; } /* pos:
0 n 1's 2's 3's
(d) /* TRUE */
while( i par ) i = i/2; /* i impar */
2. Escreva um loop, com inicializao, para somar os primeiros n nmeros naturais pares e positivos. Utilize as asseres de pr-condio, ps-condio e invariante, e a funo teto dadas abaixo:
/* pre: */ /* pos: */ /* inv: * */ /* ft: */ n > 0 s = 2 + 4 + 6 + ... + (2*n) 2 k 2*n e k par e s = k + (k+2) + ... + (2*n) k/2
b */
Obs.: O invariante abaixo seria menos eficiente pois exigiria at 2 trocas em cada iterao do loop:
/* inv:
0 n 1's 2's 3's ?
b */
3. dado um vetor b[0..n1], onde n 0. Escreva um loop (com inicializao) para inverter o vetor b (por exemplo, se inicialmente b = [1,3,5,2,6], ento para invert-lo significa modific-lo para b = [6,2,5,3,1]). Utilize as asseres de pr-condio, ps-condio e invariante, e a funo teto dadas abaixo:
/* pre: */ /* pos: */ /* inv: * * */ /* ft: */ b[0..n1] no invertido b[0..n1] invertido b[0..k1] invertido b[k..j] no invertido b[j+1..n1] invertido jk
Suponha que os coeficientes sejam dados em um vetor b[0..n]. Escreva um loop (com inicializao) para achar o valor v do polinmio para um dado valor de y. A funo teto ft: ni. Usando uma varivel auxiliar x, o invariante do loop :
/* inv: * * */ 0 i n e x = yi e v = b0 + b1*y + ... + bn*yi
5. (Hehl, 1986) Escreva um programa em C para o algoritmo apresentado no diagrama N-S abaixo. O que faz este programa? Para i=1; enquanto i<=7; passo i=i+1 Para j=1; enquanto j<=7; passo j=j+1 n = 1; x = 1; y = 1; Enquanto n > 0 n par? Sim n = n / 2; x = x * x; Imprime i, j, y; No n = n - 1; y = y * x;
Referncias Bsicas
Kernighan, B.W.; Ritchie, D.M., The C Programming Language, Prentice-Hall, Second Edition, 1988. Savitch, W.J., Pascal: An Introduction of the Art and Science of Programming, The Benjamin / Cummings Publishing Company, 1984. memria usada para armazenar as variveis locais que so necessrias para executar a funo. Estas variveis locais incluem cpias dos eventuais argumentos que so passados para a funo. Tomemos, por exemplo, a funo power, mostrada abaixo, que retorna o valor do nmero inteiro x elevado n-sima potncia. Esta funo chamada pela rotina principal main que imprime na tela todas as potncias do nmero 2 de 0 at 9.
int power( int x, int n ) { int i, p;
Introduo
Um dos aspectos que caracterizam uma linguagem de programao o mecanismo utilizado para o acionamento de uma rotina (funo). Este mecanismo varia quanto ao escopo de utilizao de memria do computador e quanto forma como os argumentos (parmetros) so passados da rotina que chama para a rotina que chamada. Uma das diferenas bsicas entre Fortran e C est justamente neste mecanismo.
O escopo de utilizao de memria deste programa pode ser esquematizado grficamente atravs de um diagrama de retngulos, tal como mostrado a seguir.
main: i : __ power: x : __ n : __ i : __ p : __
Em C, a maneira errada de chamar e escrever esta rotina (funo) est mostrada a seguir:
void swap( int x, int y ) { int temp; temp = x; x = y; y = temp; }
No diagrama, cada retngulo representa a memria ativada para executar uma funo. Ao lado de cada varivel local colocado um espao para preencher o seu valor. As variveis locais em C so chamadas de automticas pois tm alocao de memria automtica.
Isto est errado porque, como os argumentos so passados por valor, a funo swap no pode afetar os valores de a e b. Isto s seria conseguido se a e b fossem passados por referncia. bvio que este mecanismo tambm pode ser implementado em C, conforme ser mostrado na prxima seo. A vantagem da passagem de argumentos por valor est na garantia de privacidade de dados de uma determinada rotina, se este for o objetivo. Quando uma rotina chama uma funo passando parmetros por valor, ela pode ter certeza de que as variveis locais que foram usadas como parmetros no sero alteradas pela funo chamada.
10
Tambm permitido a criao de variveis que contm endereos de outras variveis. So os chamados ponteiros, que so declarados por exemplo como int *p;. Neste caso, p um ponteiro para um inteiro. Isto quer dizer que o valor de p um endereo na memria de um inteiro. Por exemplo, para um inteiro a, a instruo p = &a; atribui a p o endereo de a. Alm disso, existe a possibilidade de acessar o contedo do endereo que apontado por um ponteiro. Por exemplo, considere o programa abaixo:
void main( void ) { int a = 10; int *p; p = &a; printf( %d\n, *p ); }
A princpio a implementao deste mecanismo de passagem de argumento por referncia em C pode parecer complicada, principalmente se o programador estiver acostumado com Fortran, onde no se tem um acesso explcito a endereos de variveis e no existe variveis ponteiros para outras variveis. No entanto, a lgica da linguagem C consistente (sempre passa argumentos por valor, mesmo que sejam endereos de variveis) e consegue implementar os dois mecanismos de passagem de argumentos.
Este programa imprime o valor 10 na tela, pois o identificador *p identificado pelo compilador como o contedo do endereo que identificado por p. Com base no que foi exposto acima, a implementao da passagem de argumentos por referncia em C pode ser feita facilmente. Isto , como se tem um acesso explcito ao endereo de uma varivel, quando se deseja passar um argumento por referncia (para alterar o valor da varivel correspondente na funo chamada, por exemplo), basta que se passe (por valor) o endereo (ou um ponteiro contendo o endereo) da varivel. A implementao correta da funo swap para trocar os valores de duas variveis entre si est mostrada abaixo:
void swap( int *px, int *py ) { int temp; temp = *px; *px = *py; *py = temp; } void main( void ) { int a = 2, b = 5; swap( &a, &b ); }
No diagrama de retngulos, o ativamento de uma funo representado por um retngulo. As variveis locais so identificadas por um identificador que representa a memria utilizada pela varivel. As variveis locais que so ponteiros tambm tm setas que apontam para os identificadores correspondentes. A seguir so mostrados diagramas para a execuo do programa acima imediatamente antes de cada 11
uma das instrues com rtulos (labels L1, L2, L3, L4, L5 e L6). Antes de L1: main: a : __ 2 b : __ 5 f : __ 1
Variveis externas
Antes de L3: main: a : __ 2 b : __ 5 f : __ 1 swap: f : __ 1 px : __ py : __ temp : __ 2 Antes de L4: main: a : __ 5 b : __ 5 f : __ 1 swap: f : __ 1 px : __ py : __ temp : __ 2 A alocao de variveis externas esttica, isto , existe um espao de memria reservado para cada varivel externa j na hora que o programa ativado. As variveis externas, porque so acessadas globalmente, fornecem um meio alternativo para a comunicao entre as funes. Assim, Um programa em C consiste de um conjunto de objetos externos, que podem ser tanto variveis quanto funes. O adjetivo externo utilizado para diferenciar de objetos internos a uma funo, que so os seus parmetros (cpias de variveis passadas) e variveis locais, chamadas de variveis automticas pois tm alocao de memria automtica. Variveis externas so definidas fora de qualquer funo, e so portanto potencialmente disponveis para muitas funes (variveis externas so semelhantes s variveis definidas dentro de uma instruo COMMON de Fortran). As funes so sempre externas, pois C no permite uma funo ser definida dentro de outra funo.
12
mdulo. Elas diferem das variveis externas globais (que so visveis para todas as funes de todos os mdulos de compilao) pela instruo static que precede o tipo da varivel.
Funes estticas
Funes estticas so funces que so visveis apenas por um mdulo de compilao. Somente as funes do mdulo podem acionar (chamar) uma funo esttica. A vantagem de funes estticas que elas so privadas ao seu mdulo de compilao, podendo at repetir nomes de outras funes estticas de outros mdulos. Em C, static significa no somente permanncia em memria, mas tambm um certo grau de privacidade: variveis estticas internas so visveis apenas por uma funo; e variveis estticas externas e funes estticas so visveis apenas por um mdulo de compilao. O uso de funes estticas e variveis estticas externas auxilia a modularizao de um programa pois aumenta o grau de independncia de um mdulo em relao aos demais.
Uma varivel externa pode ser compartilhada por funes que esto localizadas em mdulos de compilao distintos (arquivos fontes distintos). Para isso, ela deve ser definida em um mdulo e declarada em outros mdulos que a utilizem, o que feito usando a instruo extern. Exemplos disso podem ser:
extern int extern int a; b;
Variveis estticas
Alm da varivel automtica (alocada automaticamente na memria quando a sua funo acionada) e da varivel externa, existe uma terceira classe que se chama varivel esttica. Variveis estticas podem tanto ser internas quanto externas. Variveis estticas internas so locais para uma determinada funo tanto quanto so as variveis automticas, mas, diferentemente destas ltimas, elas permanecem existentes na memria ao invs de irem e virem cada vez que a funo ativada. A declarao de uma varivel esttica interna difere da declarao de uma varivel automtica apenas pela instruo static que precede o tipo da varivel:
static int a;
Variveis estticas externas so locais para um mdulo de compilao (arquivo fonte), isto , s so visveis para as funes que compem o 13
Exerccios propostos
1. Desenhe uma seqncia de diagramas de retngulos para indicar o estado de execuo do programa abaixo imediatamente antes de cada instruo com rtulo Li:. Indique nestes diagramas um identificador para a varivel externa que aparece, com o valor correspondente para cada estado.
int i; void fncA( void ) { L5: i = 13; } void fncB( void ) { L4: fncA(); } void fncC( void ) { L3: fncB(); } void main( void ) { L1: i = 12; L2: fncC(); L6: }
3. Execute o programa abaixo e mostre uma seqncia de diagramas de retngulos, com identificadores para as variveis e os argumentos de funo. Os diagramas devem mostrar o estado do programa antes de cada instruo com rtulo Li:. Coloque os valores correspondentes para os identificadores. Este exerccio foi projetado para for-lo(a) a entender o mecanismo de utilizao de memria e de passagem de argumentos de funes em C, mesmo em face chamada recursiva de funes.
void fnc( int *y, int z ) { int x; if( z <= 1 ) *y = 16; else { x = z 2; L1: fnc( &x, *y 4 ); } L3: } L2: void main( void ) { int x = 6; L0: fnc( &x, x 3 ); L4: }
2. Execute os programas abaixo e mostre uma seqncia de diagramas de retngulos, com identificadores para as variveis e o argumento de funo. Os diagramas devem mostrar o estado dos programas antes de cada instruo com rtulo Li:. Coloque os valores correspondentes para os identificadores.
int x, y; void fnc(int a) { L1: a = 12; L2: y = x; } void main(void) { x = 4; L0: fnc( x ); L3: } | | | | | | | | | | | | int x, y; void fnc(int *a) { L1: *a = 12; L2: y = x; } void main(void) { x = 4; L0: fnc( &x ); L3: }
14
Referncia Bsica
Kernighan, B.W.; Ritchie, D.M., The C Programming Language, Prentice-Hall, Second Edition, 1988.
Estruturas
Uma estrutura (struct) uma coleo de uma ou mais variveis, possivelmente de tipos diferentes, agrupadas segundo um nico nome para facilidade de manuseio. Um exemplo de uma declarao de uma estrutura seria:
struct data { int dia; int mes; int ano; int dia_ano; char nome_mes[4]; };
Pode-se inclusive declarar a estrutura e definir um tipo para ela de uma s vez:
typedef struct data { int dia; int mes; int ano; int dia_ano; char nome_mes[4]; } Data;
A definio de uma varivel do tipo estrutura pode ser feita como exemplificada abaixo:
/* sem inicializao */ struct data d; /* com inicializao */ struct data d = {4,7,1776,186,"Jul"};
t = d.dia;
Estruturas tambm podem ser declaradas dentro de outras estruturas, tal como mostrado abaixo:
struct pessoa { char nome[81]; struct data nasc; };
15
A declarao de uma estrutura tambm pode ser auto-recursiva. Isto est exemplificado abaixo para a declarao e definio de tipo de um elemento de lista que aponta para o elemento seguinte (do seu mesmo tipo) na lista:
typedef struct lista { struct lista *next; int dados; } ListElem;
Vetor de estruturas
Assim como pode-se declarar um vetor de caracteres, ou um vetor de inteiros, pode-se tambm declarar um vetor de estruturas:
/* Declarao esttica: */ struct pessoa staff[100]; /* ou ainda: */ Data dias[366];
Neste caso pd um ponteiro para uma estrutura do tipo Data. O acesso de um campo da estrutura, cujo ponteiro dado, exemplificado por pd>ano, o que equivalente a (*pd).ano. Uma estrutura tambm pode conter campos que so ponteiros para estruturas. Um exemplo disto :
typedef struct pessoa { char nome[81]; struct data *nasc; } Pessoa;
E a indexao feita da mesma forma que feita para qualquer outro vetor:
/* Atrubui a "d" todos os valores * do vigsimo (ndice = 19) dia do * vetor "dias": */ Data d; d = dias[19];
Neste caso, a estrutura Pessoa tem dois campos, um o nome da pessoa e o outro um ponteiro para a data do seu nascimento. A funo abaixo mostra um exemplo do acesso a um campo da data de nascimento de uma pessoa cujo registro passado (por referncia):
16
O modelo de utilizao das funes para alocao dinmica de memria o seguinte: Toda vez que o programa precisa de um espao na memria para uma varivel (que pode ser uma estrutura) ou um vetor, ele chama uma funo de alocao de memria passando o tamanho em palavras (bytes) da memria necessria. O sistema operacional verifica se existe o tanto de memria disponvel em uma rea contgua e retorna, como valor de retorno da funo chamada, o endereo (ponteiro) onde inicia a poro de memria requisitada. Se no existe memria disponvel o valor retornado nulo. Esta memria requisitada pelo programa pode ser liberada tambm em qualquer instante da execuo. Isto feito atravs da chamada de uma funo de liberao. Isto resulta na devoluo ao sistema operacional desta poro de memria para que ela possa ser utilizada por outros clientes ou em outra fase da execuo. Existe tambm a possibilidade de realocao de uma memria que foi requisitada anteriormente para aumentar ou diminir o seu tamanho. O sistema operacional verifica se existe uma rea de memria contgua (que sempre existir caso a realocao for para um tamanho menor) e retorna o ponteiro para o nova rea (que pode inclusive ser o mesmo endereo). Caso no exista uma rea contgua, a funo de realocao retorna um valor nulo. Quando h a realocao, a poro de memria que havia sido requisitada anteriormente copiada para a nova rea. As declaraes (prototypes) das funes de alocao so as seguintes:
void *malloc( int total_size ); void *calloc( int n, int size );
void free( void *pointer_to_area ); void *realloc( void *old_area, int total_new_size );
void aloca_pessoas( int npessoas ) { pessoas = (Pessoa *)calloc(npessoas, sizeof( Pessoa ) ); } void libera_pessoas( void ) { free( pessoas ); }
Abaixo se encontra um exemplo de alocao dinmica de uma lista com trs elementos:
typedef struct lista { struct lista *next; int dados; } ListElem; static ListElem *list_head = NULL;
void aloca_lista( void ) { ListElem *elem1, *elem2, *elem3; elem1 = (ListElem *)malloc( sizeof( ListElem ) ); elem2 = (ListElem *)malloc( sizeof( ListElem ) ); elem3 = (ListElem *)malloc( sizeof( ListElem ) ); list_head = elem1>next elem2>next elem3>next } void libera_lista( void ) { ListElem *elem; while( list_head != NULL ) { elem = list_head; list_head = elem>next; free( elem ); } } elem1; = elem2; = elem3; = NULL;
A funo malloc recebe como parmetro o tamanho total de memria requisitada. A funo calloc recebe um parmetro para o nmero de entidades requisitadas e outro para o tamanho de cada entidade. As declaraes das funes de liberao e realocao esto mostradas abaixo:
17