Вы находитесь на странице: 1из 37

FACULDADE DE ENGENHARIA DE SOROCABA

LINGUAGEM DE PROGRAMAO

Mdulo 2 Alocao Dinmica e Estruturas

PROF. ANDRA

FACENS Linguagem de Programao MDULO 2 Prof. Andra

5.

ALOCAO DINMICA...............................................................................................................................................3

5.1 - INTRODUO.....................................................................................................................................................................3
5.2 - ALOCANDO ESPAO DURANTE A EXECUO DO PROGRAMA........................................................................................3
5.3 - HEAP..................................................................................................................................................................................3
5.4 - FUNO MALLOC( )..........................................................................................................................................................3
5.5 - FUNO CALLOC( )...........................................................................................................................................................6
5.6 - FUNO REALLOC( ).........................................................................................................................................................7
5.7 - FUNO FREE( )...............................................................................................................................................................8
5.8 ALOCAO DE MEMRIA NA MAIN X NA FUNO.......................................................................................................9
5.9 EXERCCIOS PROPOSTOS...............................................................................................................................................14
6.

ESTRUTURAS...............................................................................................................................................................15

6.1 INTRODUO..................................................................................................................................................................15
6.2 DEFININDO UM TIPO ESTRUTURA.................................................................................................................................15
6.3 - DECLARANDO AS VARIVEIS DO TIPO ESTRUTURA.....................................................................................................16
6.4 - DEFININDO E DECLARANDO ESTRUTURAS....................................................................................................................17
6.5 - ACESSANDO MEMBROS DA ESTRUTURA........................................................................................................................18
6.6 - MLTIPLAS ESTRUTURAS DE MESMO TIPO..................................................................................................................18
6.7 - DEFINIO DE ESTRUTURAS SEM RTULO OU ETIQUETA..........................................................................................19
6.8 - ESTRUTURAS QUE CONTM MATRIZES.........................................................................................................................19
6.9 EXEMPLO - CRIANDO UMA LISTA DE LIVROS..............................................................................................................20
6.10 - INICIALIZANDO ESTRUTURAS......................................................................................................................................21
6.11 - ATRIBUIES ENTRE ESTRUTURAS..............................................................................................................................22
6.12 - ESTRUTURAS ANINHADAS - ESTRUTURAS QUE CONTM ESTRUTURAS.....................................................................22
6.13 - MATRIZES DE ESTRUTURAS.........................................................................................................................................23
6.14 - INICIALIZANDO ESTRUTURAS COMPLEXAS................................................................................................................25
6.15 EXERCCIOS PROPOSTOS.............................................................................................................................................26
7.

ESTRUTURAS COMPLEXAS.....................................................................................................................................27

7.1 - ESTRUTURAS E PONTEIROS............................................................................................................................................27


7.2 - PONTEIROS PARA ESTRUTURAS.....................................................................................................................................27
7.2.1 - OPERADOR DE ACESSO INDIRETO.................................................................................................................................28
7.2.2 - OPERADOR DE INDIREO (*).......................................................................................................................................28
7.2.3 - NOME DA ESTRUTURA..................................................................................................................................................28
7.3 - PONTEIROS E MATRIZES DE ESTRUTURAS....................................................................................................................29
7.4 - PASSANDO ESTRUTURAS COMO ARGUMENTOS PARA FUNES..................................................................................31
7.5 ESTRUTURAS E ALOCAO DINMICA.........................................................................................................................33
7.6 EXERCCIOS PROPOSTOS...............................................................................................................................................35

FACENS Linguagem de Programao MDULO 2 Prof. Andra

5. ALOCAO DINMICA
5.1 - Introduo
A nica finalidade das variveis simples e matrizes alocar espao suficiente na memria para
armazenar valores. E se pudssemos encontrar algum espao disponvel na memria sem ter que criar
uma varivel? Nesse caso, poderamos us-lo para armazenar diretamente os valores e bastaria um
ponteiro que indicasse a posio do primeiro valor e uma varivel que indicasse a quantidade de
elementos armazenados, exatamente como a matriz previamente definida. Mas como fazer para
localizar reas de memria disponveis para armazenagem ?

Usa-se funes para alocar espao na memria enquanto o programa est sendo
executado um processo conhecido como "alocao dinmica".

5.2 - Alocando Espao durante a Execuo do Programa


H funes de alocao da memria em C. Ao chamar estas funes, voc deve especificar o
nmero de bytes necessrios, a funo localiza e reserva um bloco de memria no tamanho apropriado
e retorna o endereo do primeiro byte desse bloco.
Esse tipo de funo retorna um endereo, e seu tipo de retorno um ponteiro para o tipo void.
Por que void ? Porque um ponteiro para dados do tipo void compatvel com todos os tipos de dados,
i.e., ele genrico. Como a memria alocada pode ser usada para armazenar qualquer dos tipos de
dados vlidos em C, o tipo de retorno void o mais apropriado.

5.3 - Heap
O heap ou rea de alocao dinmica consiste de toda a memria disponvel que no foi usada
para um outro propsito. Em outras palavras, o heap simplesmente o resto da memria.
A linguagem C oferece um conjunto de funes que permitem a alocao ou liberao
dinmica de memria do heap, como : malloc( ), calloc( ), realloc( ) e free( ).

5.4 - Funo malloc( )


Arquivo de cabealho:
stdlib.h
sintaxe:
void* malloc(tamanho);
onde:
tamanho corresponde a um inteiro sem sinal, que representa a quantidade em bytes de memria
requerida.

FACENS Linguagem de Programao MDULO 2 Prof. Andra


A cada chamada de malloc( ) devemos inform-la do tamanho do bloco que queremos guardar.
Esta informao pode ser conhecida do programador ou podemos utilizar o operador unrio chamado
sizeof( ), que fornece um inteiro, igual ao tamanho, em bytes, da varivel ou do tipo do dado em
questo.
A funo malloc( ) retorna um ponteiro para o primeiro byte do bloco de memria alocado.
Quando incapaz de alocar a quantidade solicitada de memria, seu retorno nulo (NULL). Sempre
que tentarmos alocar memria, mesmo que seja uma pequena quantidade, devemos verificar o valor de
retorno.
Por exemplo, podemos usar malloc( ) para alocar a memria para armazenar uma nica
varivel do tipo int. Em primeiro lugar, declaramos um ponteiro para o tipo int:
int

*ptr;

A seguir, chamamos malloc( ) passando o tamanho do bloco de memria desejado. Como um


tipo int ocupa 4 bytes, precisamos de um bloco de 4 bytes. O valor retornado por malloc ( ) atribudo
ao ponteiro:
ptr = (int*) malloc(sizeof(int*));
Esta instruo aloca um bloco de memria com 4 bytes e atribui o endereo inicial ao ponteiro
ptr. Ao contrrio das variveis que so declaradas no programa, esse bloco de memria no tem
qualquer nome e s pode ser referenciado atravs do ponteiro. Por exemplo, para armazenar o valor
10 nesse bloco, devemos escrever:
*ptr = 10;
A alocao de matrizes usando malloc( ) quase idntica a de uma nica varivel do tipo int. A
principal diferena que precisamos saber antecipadamente quantos bytes devero ser alocados - ou
seja, qual ser o nmero mximo de valores na matriz. Esse valor mximo depende das necessidades
do programa. Para exemplificar, iremos alocar uma matriz com 100 valores, o que resulta em 400
bytes. Em primeiro lugar, teramos que declarar um ponteiro para o tipo int, e depois chamar malloc( ).
int *ptr;
ptr = (int *) malloc(400);
Agora ptr est apontando para um bloco reservado de 400 bytes, que pode ser usado para a
armazenagem e manipulao de inteiros. Podemos usar o ponteiro ptr exatamente como faramos se o
programa tivesse alocado explicitamente o mesmo espao atravs de uma declarao de matriz:
int mat[100];
O uso de malloc( ) permite que o programa aloque espao conforme seja necessrio.
Evidentemente, o espao disponvel para armazenagem no ilimitado; ele depende tanto da
quantidade de memria instalada no computador quanto das outras necessidades de armazenagem do
prprio programa. Se a memria disponvel no for suficiente, malloc( ) retornar um valor 0 (nulo).
Portanto, devemos testar o valor de retorno de malloc ( ) para ter certeza de que a memria solicitada
foi alocada adequadamente. O valor de retorno de malloc( ) deve sempre ser testado contra a constante
simblica NULL que definida em STDLIB.H.

FACENS Linguagem de Programao MDULO 2 Prof. Andra


Obs.:
1)
Nunca devemos presumir que a funo malloc ( ) tenha conseguido reservar a memria que
lhe pedimos. Pois de fato, no ordenamos funo que aloque memria; apenas lhe perguntamos se
isso pode ser feito.
2)

O que significa a expresso (char *) ou (int *) ou (float *) precedendo malloc( ) ?

A funo malloc( ) retorna um ponteiro para o tipo void, portanto esse ponteiro deve ser
moldado para o tipo apropriado antes de ser usado. E para isso usamos a converso de tipos, na
verdade um operador unrio chamado operador de molde, que consiste em colocar um parnteses
envolvendo o tipo de dado desejado.
Ex.: A funo sqrt( ), retorna a raiz quadrada de um nmero do tipo double e temos uma varivel
float:
float n;
double resposta;
resposta = sqrt ((double)n);

/* converte n antes de us-lo na funo sqrt */

Portanto, devemos indicar que o valor retornado por malloc( ) ser do tipo ponteiro para char ou int ou
float.
Exemplo 1 aloca memria para uma matriz com 50 valores do tipo int.
include <stdio.h>
include <stdlib.h>
int *numeros;
main( )
{
if
( (numeros = (int *) malloc(50 * sizeof(int) ) ) = = NULL)
printf("Espao insuficiente para alocar buffer \n");
else
printf("Matriz foi alocada");
}/* main */
Exemplo 2 aloca memria para uma matriz com 10 valores do tipo float.
include <stdio.h>
include <stdlib.h>
float *numeros;
main( )
{
if
( (numeros = (float *) malloc(10 * sizeof(float) ) ) = = NULL)
printf("Espao insuficiente para alocar buffer \n");
else
printf("Matriz foi alocada");
}/* main */
5

FACENS Linguagem de Programao MDULO 2 Prof. Andra


O ponteiro ptr aponta para o valor inicial (letra A) e utilizamos outro ponteiro p para inserir
valores no espao reservado, ou seja, incrementamos p e preservamos ptr, caso contrrio
perderamos o valor inicial da memria alocada. Devemos lembrar que este bloco de memria
no contm nome, e o programa apenas sabe onde ele se encontra.

5.5 - Funo calloc( )


A funo calloc ( ) ao invs de alocar um grupo de bytes como malloc ( ), ela aloca memria
para um grupo de objetos.
Arquivo de cabealho:
stdlib.h
sintaxe:
void* calloc(num, tamanho);
onde:
num - corresponde a um inteiro sem sinal, o nmero de objetos para os quais a memria deve ser
alocada.
tamanho - corresponde a um inteiro sem sinal, o tamanho de cada objeto em bytes.
Se a alocao for bem-sucedida, toda a memria alocada inicializada com o valor 0 e a funo
retorna um ponteiro para void para o primeiro byte. Se a alocao fracassar ou se num ou size
forem iguais a zero, a funo retorna NULL.
Devemos

usar o operador molde se quisermos um ponteiro para um tipo diferente.

Exemplo 1 - aloca memria para 100 elementos do tipo long


long *ptr;
ptr = (long *) calloc (l00, sizeof (long));
if
(ptr = = NULL)
printf("Espao insuficiente \n");
else
printf("Memoria alocada");
O primeiro argumento o nmero de clulas de memria desejada. O segundo argumento o
tamanho de cada clula em bytes.
Neste caso, long usa quatro bytes, ento esta instruo alocar espao para 100 unidades de
quatro bytes ou seja 400 bytes.
Exemplo 2 programa que aloca a quantidade de variveis int estipulada pelo usurio.
#include <stdio.h>
#include <stdlib.h>
main()
{
unsigned num;
int *ptr;
6

FACENS Linguagem de Programao MDULO 2 Prof. Andra


printf("Digite o numero de variveis do tipo int: ");
scanf("%i", &num);
ptr = (int *) calloc(num, sizeof(int));
if (ptr != NULL)
puts("Memria alocada sem problemas.");
else
puts("Erro na alocao de memria.");
}
Este programa recebe um valor do usurio. Esse nmero determina a quantidade de espao a
ser alocado. O programa tenta alocar memria suficiente para conter o nmero especificado de
variveis. Se a alocao fracassar, o valor de retorno de calloc( ) NULL; caso contrrio, um
ponteiro para a rea de memria alocada. Neste programa, o valor de retorno de calloc ( ) colocado
em um ponteiro para o tipo int chamado ptr. Uma instruo if verifica o resultado da alocao com
base no valor de ptr e imprime uma mensagem apropriada.
Digite diferentes valores e veja qual o mximo de memria que voc consegue alocar sem
problemas. Esse limite depende, at certo ponto, da configurao do sistema. Em alguns sistemas, a
alocao de espao para at 25.000 ocorrncias do tipo int feita sem problemas, mas a alocao de
espao para 30.000 fracassa.

5.6 - Funo realloc( )


Muda o tamanho de um bloco de memria que tenha sido alocado anteriormente com malloc( )
ou calloc( ).
Arquivo de cabealho:
stdlib.h
sintaxe:
void* realloc(*ptr, tamanho);
onde:
ptr corresponde a um ponteiro para o tipo void, aponta para o bloco original de memria.
tamanho - corresponde a um inteiro sem sinal, especifica o novo tamanho desejado, em bytes.
Os resultados possveis do uso realloc( ) so:

se houver espao suficiente para expandir o bloco de memria referenciado por ptr, a memria
adicional alocada e a funo retorna ptr.

se no houver espao suficiente para expandir o bloco atual, um novo bloco do tamanho
especificado em tamanho alocado e os dados existentes so copiados do bloco original para o
incio do novo bloco. A seguir, o bloco original liberado e a funo retorna um ponteiro para o
novo bloco.

se o argumento ptr for NULL, a funo atua como malloc( ), alocando um bloco de tamanho bytes
e retornando um ponteiro para ele.

FACENS Linguagem de Programao MDULO 2 Prof. Andra

se o argumento tamanho for 0, a memria indicada por ptr liberada e a funo retorna NULL.

se no houver memria suficiente para a realocao (tanto expandindo o bloco original quanto
alocando um novo bloco), a funo retorna NULL e o bloco original permanece inalterado.

5.7 - Funo free( )


Ao usarmos malloc( ), calloc( ) ou realloc( ) alocamos parte do total de memria dinmica
disponvel para o programa. Esse total, que costuma ser chamado de heap, finito. Portanto, quando o
programa j no estiver utilizando algum bloco da memria alocada, aconselhamos desalocar", ou
liberar, essa memria, tornando-a disponvel para alocaes futuras. Para liberarmos a memria que foi
alocada dinamicamente, usamos a funo free ( ).
Arquivo de cabealho:
sintaxe:
void free (*ptr);

stdlib.h

onde:
ptr corresponde a um ponteiro para o tipo void, aponta para o incio do bloco de memria a ser
liberado.
A funo free ( ) libera a memria referenciada por ptr. Essa memria deve ter sido alocada
usando malloc( ), calloc( ) ou realloc( ). Se ptr for NULL, free ( ) no faz nada.
A funo free( ) declara o seu argumento como um ponteiro para void. A vantagem desta
declarao que ela permite que a chamada funo seja feita com um argumento ponteiro para
qualquer tipo de dado.
Exemplo1 - libera memria alocada por funo desenvolvida em calloc( ).
liberamem()
{
long *ptr, *alocamem();
ptr = alocamem();
free(ptr);
}

/* alocamem() - funo que aloca memria usando calloc( ) - exemplo2 */

Exemplo2 - este programa tenta alocar dois blocos de memria.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TAMBLOCO 30000
main( )
{
void *ptrl, *ptr2;

FACENS Linguagem de Programao MDULO 2 Prof. Andra


ptr1 = malloc(TAMBLOCO);

/* tenta alocar o 1 bloco */

if (ptr1 = = NULL)
printf("\n Tentativa de alocar %i bytes falhou", TAMBLOCO);
else
{
printf("\n Primeira alocao de %i bytes realizada", TAMBLOCO);
ptr2 = malloc(TAMBLOCO);
/* tenta alocar o 2 bloco */
if (ptr2 != NULL)
printf("\n Segunda alocao de %i bytes realizada", TAMBLOCO);
else
{
printf("\n Segunda tentativa de alocar %i bytes falhou", TAMBLOCO);
free (ptr1);
printf("\n Liberando o primeiro bloco);
ptr2 = malloc(TAMBLOCO);
if (ptr2 != NULL)
printf("\n Depois de free(), alocao de %i bytes realizada", TAMBLOCO);
}/* else */
}/* else */
}/* main */
Este programa tenta alocar dinamicamente dois blocos de memria, usando a constante
TAMBLOCO para determinar o tamanho de cada bloco. Porm, a 2 alocao s ocorrer se a 1 for
bem sucedida.

ptr1 corresponde a 1 alocao. Determinamos o resultado da alocao verificando se o valor de


retorno foi NULL. Se a alocao no foi bem sucedida (valor de retorno = NULL) o programa
encerrado. Caso contrrio, tentaremos alocar um 2 bloco de memria.

ptr2 corresponde a 2 alocao. Novamente verificamos o resultado, porm agora se o


procedimento foi bem sucedido (valor de retorno diferente de NULL). Se a 2 alocao ocorreu
sem problemas, o programa finalizado, caso contrrio, o primeiro bloco liberado com free ( ) e
feita uma nova tentativa de alocao.

5.8 Alocao de Memria na Main X na Funo


Para alocarmos memria dinamicamente na main, devemos declarar um ponteiro e utilizar
malloc(), calloc() ou realloc(). Porm, quando utilizamos funo, devemos lembrar que a memria no
pode ser conhecida apenas na funo, mas tambm na main. Portanto, devemos declarar um ponteiro
na main e a funo pode ser feita de 2 formas:

FACENS Linguagem de Programao MDULO 2 Prof. Andra

Chamada por Referncia devemos passar o endereo do ponteiro declarado na main,


portanto, a funo receber como parmetro ponteiro para ponteiro.
Chamada por Valor s conseguimos trabalhar dessa forma, se a funo retornar o
endereo alocado para o ponteiro declarado na main, permitindo assim, o acesso deste
memria alocada. Caso contrrio o ponteiro na main continuar NULL e ao sairmos da funo
perdemos a referncia da memria alocada. Lembre-se que as variveis (inclusive ponteiro)
declaradas dentro da funo, deixam de existir assim que a funo termina.

Verso utilizando Chamada por Referncia


#include <stdio.h>
#include <stdlib.h>
void aloca(int **p, int tam);

//passa o endereo do ponteiro declarado na main

main( )
{
int *ptr=NULL;
printf("\nAloca memoria na Funcao e na Main\n");
printf("\nChamada por Referencia - passa ENDERECO do ponteiro\n");
printf("\nFuncao main - antes de alocar");
printf("\nEndereco ptr = %u \nConteudo %u = %u",&ptr,&ptr,ptr);
aloca(&ptr, 1);
//chamada por referencia
printf("\n\nFuncao main - depois de alocar");
printf("\nEndereco ptr = %u \nConteudo %u = %u\n\n\n",&ptr,&ptr,ptr);
system("pause");
}//main
void aloca(int **p, int tam)
{
printf("\n\nFuncao aloca - antes de alocar");
printf("\nEndereco p = %u \tConteudo p = %u (Endereco ptr)",&p,p);
printf("\nConteudo %u = %u\n",p,*p);
if((*p=(int*)realloc(*p, tam*sizeof(int)))== NULL)
{
printf("Erro de alocacao");
exit(1);
}
printf("\n\nFuncao aloca - depois de alocar");
printf("\nEndereco p = %u \tConteudo p = %u (Endereco ptr)",&p,p);
printf("\nConteudo %u = %u\n",p,*p);
}//aloca
Verso utilizando Chamada por Valor com RETORNO do endereo alocado
#include <stdio.h>
#include <stdlib.h>
int*

aloca(int *p, int tam);

//retorna o endereo da memria alocada

10

FACENS Linguagem de Programao MDULO 2 Prof. Andra


main()
{
int *ptr=NULL;
printf("\nAloca memoria na Funcao e RETORNA para a Main\n");
printf("\nChamada por Valor - passa CONTEUDO do ponteiro\n");
printf("\nFuncao main - antes de alocar");
printf("\nEndereco ptr = %u \nConteudo %u = %u",&ptr,&ptr,ptr);
ptr = aloca(ptr, 1);
//chamada por valor
printf("\n\nFuncao main - depois de alocar");
printf("\nEndereco ptr = %u \nConteudo %u = %u\n\n\n",&ptr,&ptr,ptr);
system("pause");
}//main
int* aloca(int *p, int tam)
{
printf("\n\nFuncao aloca - antes de alocar");
printf("\nEndereco p = %u \nConteudo p = %u (Conteudo ptr)",&p,p);
if((p=(int*)realloc(p, tam*sizeof(int)))== NULL)
{
printf("Erro de alocacao");
exit(1);
}
printf("\n\nFuncao aloca - depois de alocar");
printf("\nEndereco p = %u \nConteudo p = %u (Conteudo ptr)",&p,p);
}//aloca
ERRO: Verso utilizando Chamada porValor sem RETORNO do endereo alocado
#include <stdio.h>
#include <stdlib.h>
void aloca(int *p, int tam);

//NO retorna o endereo da memria alocada

main()
{
int *ptr=NULL;
printf("\nERRO pois aloca memoria apenas na Funcao e nao na Main\n");
printf("\nChamada por Valor - passa CONTEUDO do ponteiro\n");
printf("\nFuncao main - antes de alocar");
printf("\nEndereco ptr = %u \nConteudo %u = %u",&ptr,&ptr,ptr);
aloca(ptr, 1);
printf("\n\nFuncao main - depois de alocar");
printf("\nEndereco ptr = %u \nConteudo %u = %u\n\n\n",&ptr,&ptr,ptr);
NULL
system("pause");
}//main

//chamada por valor


//ptr

continua

void aloca(int *p, int tam)


{
printf("\n\nFuncao aloca - antes de alocar");
11

FACENS Linguagem de Programao MDULO 2 Prof. Andra


printf("\nEndereco p = %u \nConteudo p = %u (Conteudo ptr)",&p,p);
if((p=(int*)realloc(p, tam*sizeof(int)))== NULL)
{
printf("Erro de alocacao");
exit(1);
}
printf("\n\nFuncao aloca - depois de alocar");
printf("\nEndereco p = %u \nConteudo p = %u",&p,p);
}//aloca

Exemplo de Alocao de Memria na Main X na Funo


Alocar espao para 10 nmeros inteiros. Mostrar o endereo e receber do usurio os valores. Em
seguida mostrar novamente o endereo e o respectivo valor de cada elemento.
Verso para Alocao feita na main( )
#include <stdio.h>
#include <stdlib.h>
void recebe (int *p, int tam);
void imprime (int *p, int tam);
main( )
{
int
*ptr=NULL;
if((ptr = (int *) realloc(ptr, 10 * sizeof(int))) == NULL)
{
printf(Erro na alocao);
exit(1);
}
recebe(ptr,10);
imprime(ptr,10);
system(pause);
}//main
void recebe (int *p, int tam)
{
int i;
printf(\nFuncao recebe Digite os valores \n);
for(i=0;i<tam;i++)
{
printf(Endereco: %u Valor = ,p+i);
scanf(%i,p+i);
}
}//recebe
void imprime (int *p, int tam)
{
12

FACENS Linguagem de Programao MDULO 2 Prof. Andra


int

i;

printf(\nFuncao imprime Mostra os valores \n);


for(i=0;i<tam;i++)
printf(Endereco: %u Valor = %i,p+i,*(p+i));
}//imprime
Verso para Alocao feita por funo( )
#include <stdio.h>
#include <stdlib.h>
void aloca (int **p, int tam);
void recebe (int *p, int tam);
void imprime (int *p, int tam);

//ponteiro p/ ponteiro recebe endereo do ponteiro

main( )
{
int
*ptr=NULL;
aloca(&ptr,10);
recebe(ptr,10);
imprime(ptr,10);
system(pause);
}//main

//chamada por referncia endereo do ptr

void aloca (int **p, int tam)


{
if((*ptr = (int *) realloc(*ptr, 10 * sizeof(int))) == NULL)
{
printf(Erro na alocao);
exit(1);
}
printf(\nFuncao aloca Endereco: %u, *p);
}//aloca
void recebe (int *p, int tam)
{
int i;
printf(\nFuncao recebe Digite os valores \n);
for(i=0;i<tam;i++)
{
printf(Endereco: %u Valor = ,p+i);
scanf(%i,p+i);
}
}//recebe
void imprime (int *p, int tam)
{
int i;
13

FACENS Linguagem de Programao MDULO 2 Prof. Andra


printf(\nFuncao imprime Mostra os valores \n);
for(i=0;i<tam;i++)
printf(Endereco: %u Valor = %i,p+i,*(p+i));
}//imprime

5.9 Exerccios Propostos


1. Alocar espao para 10 nmeros reais. Mostrar o endereo e receber do usurio os valores. Em
seguida, alterar esses valores, somando 30 a cada elemento. Mostrar novamente o endereo (que
deve ser o mesmo) com o novo valor. Utilizar funo para alocao dinmica.
2. Aloque espao para uma seqncia de nmeros reais escolhida pelo usurio. Receba os valores e
imprima-os em ordem inversa. Utilizar funo para alocao dinmica.
3. Idem ao exerccio anterior, porm a seqncia de nmeros reais dever ser digitada pelo usurio,
at que este escolha a opo N (Deseja continuar? (S/N)). Utilizar funo para alocao
dinmica.
4. Aloque dinamicamente a seqncia de nmeros reais digitados pelo usurio, at que este escolha a
opo N (Deseja continuar? (S/N)). Em seguida, exiba a mdia dos elementos (no considerar as
ocorrncias com valor = 0). Utilizar funo para alocao dinmica.
5. Alocar espao para armazenar as temperaturas dirias registradas durante um ms. O programa
deve mostrar diariamente (a medida que as temperaturas so includas) a maior temperatura e o
dia em que ocorreu. Utilizar funo para alocao dinmica.

14

FACENS Linguagem de Programao MDULO 2 Prof. Andra

6. ESTRUTURAS
6.1 Introduo
Quando nos deparamos com um problema onde desejamos agrupar um conjunto de tipos de
dados no similares sob um nico nome, nosso primeiro impulso seria usar uma matriz. Porm, como
matrizes requerem que todos os seus elementos sejam do mesmo tipo, provavelmente foraramos a
resoluo do problema selecionando uma matriz para cada tipo de dado, resultando em um programa
ineficiente.
O problema de agrupar dados desiguais em C resolvido pelo uso de estruturas
Uma estrutura uma coleo de uma ou mais variveis, possivelmente de tipos diferentes,
colocadas juntas sob um nico nome. (Estruturas so chamadas "registros" em algumas linguagens).
uma outra maneira de representao de dados em C, que servir para a elaborao de um arquivo de
dados na memria acessado atravs de uma lista encadeada.
Um exemplo tradicional de uma estrutura o registro de uma folha de pagamento, onde um
funcionrio descrito por um conjunto de atributos tais como:
nome (string)
n do seu departamento (int)
salrio (float) e assim por diante.
Provavelmente, haver outros funcionrios, e voc vai querer que o seu programa os guarde
formando uma matriz de estruturas.
O uso de uma matriz de vrias dimenses no resolveria o problema, pois todos os elementos
de uma matriz devem ser de um tipo nico, portanto deveramos usar vrias matrizes:
uma de caracteres para os nomes
uma de inteiros para nmero do departamento
uma float para os salrios e assim por diante.
Esta no seria uma forma prtica de manejar um grupo de caractersticas que gostaramos que
tivessem um nico nome: funcionrio.
Uma estrutura consiste de um certo nmero de itens de dados, chamados membros da estrutura,
que no necessitam ser de mesmo tipo, agrupados juntos.

6.2 Definindo um Tipo Estrutura


Primeiro, devemos definir o tipo da estrutura que queremos criar. Uma estrutura pode conter
qualquer nmero de membros de diferentes tipos. O programa deve avisar o compilador de como
formada uma estrutura antes de seu uso.
sintaxe:
struct nome_estrutura{
membros_estrutura;
};
onde:
nome_estrutura rtulo ou etiqueta da estrutura, segue as mesmas regras de nomes de variveis.
15

FACENS Linguagem de Programao MDULO 2 Prof. Andra


membros_estrutura lista de variveis, contm o tipo e o nome de cada varivel da estrutura.
Ex.:
struct facil {
int
num;
char c;
};
Estas instrues definem um novo tipo de dado chamado struct facil. Cada varivel deste tipo
ser composta por dois elementos:
uma varivel inteira chamada num
e uma varivel char chamada c.
Esta instruo no declara qualquer varivel, e ento no reservado nenhum espao de
memria. Somente mostrado ao compilador como formado o tipo struct facil.
A palavra struct informa ao compilador que um tipo de dado est sendo declarado e o nome
facil chamado rtulo e nomeia a estrutura que est sendo definida.
O rtulo no o nome de uma varivel, mas o nome de um tipo. Os membros da estrutura
devem estar entre chaves, e a instruo termina por ponto e vrgula.
UMA ESTRUTURA UM TIPO DE DADO CUJO FORMATO DEFINIDO PELO
PROGRAMADOR.

6.3 - Declarando as Variveis do Tipo Estrutura


Aps definirmos nosso novo tipo de dado. Podemos, ento, declarar uma ou mais variveis
deste tipo.
Ex.:
a varivel uma estrutura
a estrutura chama-se facil
o nome da varivel do tipo estrutura x
struct facil

x;

Em nosso exemplo, declaramos a varivel x como sendo do tipo struct facil.


Esta instruo executa uma funo similar s declaraes de variveis que j conhecemos
como:
float
int

f;
num;

Ela solicita ao compilador a alocao de espao de memria suficiente para armazenar a


varivel x que do tipo struct facil, neste caso 6 bytes (4 bytes para o inteiro e 2 bytes para o
caractere).

16

FACENS Linguagem de Programao MDULO 2 Prof. Andra


6.4 - Definindo e Declarando Estruturas
Se preferirmos, podemos definir e declarar a estrutura de uma nica vez.
Ex.:
struct facil {
int
num;
char c;
}x;
Esta instruo define o tipo de estrutura facil e declara uma estrutura desse tipo, chamada x.
Dizemos que x instncia do tipo facil e contm 2 membros, um int chamado num e outro char
chamado c
OBS.: C permite definir explicitamente novos nomes aos tipos de dados, utilizando a palavra-chave
typedef. Declaraes com typedef no produzem novos tipos de dados, apenas cria sinnimos.
sintaxe:
typedef

tipo_existente

novonome;

Ex.:
1)
typedef
float
portanto, demos usar:
real a, b;

real;

//o compilador reconhece real como outro nome para float


// declarao de 2 variveis do tipo real (float)

2)
struct facil {
int
num;
char c;
}x;
typedef struct facil facil; //o compilador reconhece facil como outro nome p/ struct facil
facil x;
ou
typedef struct facil {
int
num;
char c;
}facil;
facil

x;

ou
typedef struct {
int
num;
char c;
}facil;
facil

//sem etiqueta

x;
17

FACENS Linguagem de Programao MDULO 2 Prof. Andra


6.5 - Acessando Membros da Estrutura
Agora que j criamos uma varivel do tipo estrutura, precisamos acessar (referenciar) os seus
membros.
Quando usamos uma matriz, podemos acessar um elemento individual atravs do ndice:
matriz[7].
Estruturas usam uma maneira de acesso diferente: o operador ponto (.), que tambm
chamado operador de associao.
Ex.:

A sintaxe apropriada para referenciar num que parte da estrutura x, :


x.num

O nome da varivel que precede o ponto o nome da estrutura e o nome que o segue o de um
membro especfico da estrutura. As instrues:
x.num = 2;
x.c = 'Z'

// atribui 2 ao membro num da estrutura x


// atribui Z ao membro c da estrutura x

O OPERADOR (.) CONECTA O NOME DA VARIVEL ESTRUTURA A UM MEMBRO DA


ESTRUTURA.
Para exibir na tela:
printf("x.num = %i, x.c = %c \n", x.num, x.c);
A sada ser:
x.num = 2, x.c = Z

6.6 - Mltiplas Estruturas de Mesmo Tipo


Do mesmo modo como podemos ter vrias variveis do tipo int em um programa, podemos
tambm ter qualquer nmero de variveis do tipo de uma estrutura predefinida.
Ex.:

Vamos declarar duas variveis, x1 e x2, do tipo struct facil.

struct facil {
int
num;
char c;
};
struct facil
xl, x2;
ou, se preferir:
struct facil {
int
num;
char c;
}x1, x2;
O efeito o mesmo, e o programa torna-se mais compacto.

18

FACENS Linguagem de Programao MDULO 2 Prof. Andra


6.7 - Definio de Estruturas Sem Rtulo ou Etiqueta
A conveno normal a de usar a etiqueta da estrutura quando a expectativa criar vrias
variveis do mesmo tipo estrutura. Porm, se voc espera usar uma nica declarao de varivel do
tipo estrutura, voc pode combinar a declarao com a definio da estrutura e omitir a etiqueta:
struct {
int
num;
char c;
} x1, x2;

6.8 - Estruturas que Contm Matrizes


Podemos definir uma estrutura cujos membros incluam uma ou mais matrizes. A matriz pode
ser de qualquer tipo de dados vlido em C (char, int, float, double, etc.).
Ex.:
struct data{
int
char
};

x[2];
y[10];

Definem uma estrutura do tipo data cujos membros so uma matriz inteira com 2 elementos
chamada x e uma matriz de caracteres com 10 elementos chamada y. A seguir, poderamos declarar
uma estrutura chamada record baseada no tipo data:
struct data

record;

A organizao desta estrutura mostrada a seguir:


record.x[0]
record
record.x
record.y

record.y[8]
Observe que nessa figura os elementos da matriz x ocupam o qudruplo do espao dos
elementos da matriz y. Isto acontece porque, um elemento do tipo int normalmente exige 4 bytes, ao
passo que um elemento do tipo char normalmente s exige 1 byte.
O acesso aos elementos individuais de uma matriz que um membro de uma estrutura feito
atravs de uma combinao de operadores de membros e subscritos de matrizes:

19

FACENS Linguagem de Programao MDULO 2 Prof. Andra


record.x[1] = 100;
record.y[2] = 'x';
O nome de uma matriz, quando usado sem os colchetes, um ponteiro para essa matriz.
Como isto tambm se aplica s matrizes que so membros de estruturas, a expresso
record.y
um ponteiro para o primeiro elemento da matriz y dentro da estrutura record. Podemos, portanto,
imprimir o contedo de y [ ] na tela usando a instruo
puts(record.y);

6.9 Exemplo - Criando uma Lista de Livros


A lista de livros compreende uma variedade de informaes como:
ttulo
autor
editora
nmero de pginas
nmero do registro de biblioteca
preo, etc.
Nosso objetivo desenvolver um programa que controle um arquivo simples e mostre um dos
mais teis caminhos de organizao de dados em C: uma matriz de estruturas.
Para simplificar o problema, a nossa lista ser formada, a princpio, somente pelo ttulo do
livro, representado por uma matriz de caracteres e o nmero do registro de biblioteca representado por
um inteiro. Estas informaes so fornecidas pelo usurio atravs da entrada padro (teclado) e depois
impressas na sada padro (vdeo).
Ex.:

Na primeira verso a nossa lista ser limitada em apenas dois livros.

#include <stdio.h>
#include <stdlib.h>
// funo atoi( )
struct livro {
char
titulo[30];
int
regnum;
};
main( )
{
struct livro
livro1,livro2;
char numstr[8];
printf("\n Livro l \n Digite titulo: ");
gets(livro1.titulo);
printf("Digite o numero do registro (3 digitos): ");
gets(numstr);
livro1.regnum = atoi(numstr);
printf("\n Livro 2 \n Digite titulo: ");
gets (1ivro2.titulo);
20

FACENS Linguagem de Programao MDULO 2 Prof. Andra


printf("Digite o numero do registro (3 digitos): ");
gets(numstr);
1ivro2.regnum = atoi (numstr);
printf("\n Lista de livros:\n");
printf(" Titulo: %s\n",livrol.titulo);
printf(" Numero do registro: %3i \n",livrol.regnum);
printf(" Titulo: %s\n",livro2.titulo);
printf(" Numero do registro: %3i \n",livro2.regnum);
}
Uma simples execuo do programa ter a seguinte sada:
Livro 1.
Digite titulo: Helena
Digite o numero do registro (3 digitos): 102
Livro 2.
Digite titulo: Iracema
Digite o numero do registro (3 digitos): 321
Lista de livros:
Titulo: Helena
Numero do registro: 102
Titulo: Iracema
Numero do registro: 321
Poderamos ter usado a funo scanf() para ler o nmero do registro dos livros, como na
instruo:
scanf("%i", &livro1.regnum);
que surtiria o mesmo efeito do uso de gets() e atoi(). Porm, preferimos usar gets() e atoi(), pois no
provocam problemas com o buffer do teclado, se o usurio digitar espaos antes de digitar o nmero.
A funo atoi( ), converte uma string ASCII num inteiro correspondente.

6.10 - Inicializando Estruturas


Ns j aprendemos como inicializar variveis simples e matrizes:
int
num = 5;
int
mat[ ] = { 1, 2, 3, 4, 5 };
Ex.: Uma verso modificada do programa, em que os dados dos 2 livros esto contidos na instruo
de inicializao dentro do programa, em vez de serem solicitados ao usurio.
struct livro {
char titulo[30];
int regnum;
};
main()
{
struct livro
struct livro

livro1 = {"Helena",102};
livro2 = {"Iracema",321};
21

FACENS Linguagem de Programao MDULO 2 Prof. Andra


printf("\nLista de livros:\n");
printf("Titulo: %s \n", livro1.titulo);
printf("Numero do registro: %3i \n", livrol.regnum);
printf("Titulo: %s \n", livro2.titulo);
printf("Numero do registro: %3i \n", livro2.regnum);
} // main
Aqui, depois da declarao usual do tipo estrutura, as duas variveis estrutura so declaradas e
inicializadas.
Da mesma forma como inicializamos matrizes, o sinal de igual usado e em seguida a abertura
da chave que ir conter a lista de valores. Os valores so separados por vrgulas.

6.11 - Atribuies entre Estruturas


Na verso original do C definida por Kernighan e Ritchie, impossvel atribuir o valor de uma
varivel estrutura a outra do mesmo tipo, usando uma simples expresso de atribuio.
Nas verses mais modernas de C, esta forma de atribuio j possvel. Isto , se livro1 e
livro2 so variveis estrutura do mesmo tipo, a seguinte expresso pode ser usada:
livro2 = livro1;
O VALOR DE UMA VARIVEL ESTRUTURA PODE SER ATRIBUDO A OUTRA
VARIVEL ESTRUTURA DO MESMO TIPO.
Quando executamos esta atribuio, os dados para os 2 livros sero exatamente os mesmos.
QUANDO ATRIBUMOS UMA ESTRUTURA A OUTRA, TODOS OS VALORES NA
ESTRUTURA ESTO REALMENTE SENDO ATRIBUDOS PARA OS
CORRESPONDENTES ELEMENTOS DA OUTRA ESTRUTURA.
Uma expresso de atribuio to simples no pode ser usada para matrizes, que devem ser
atribudas elemento a elemento.

6.12 - Estruturas Aninhadas - Estruturas que contm Estruturas


Exatamente como podemos ter matrizes de matrizes, podemos ter estruturas que contm outras
estruturas. O que pode ser um poderoso caminho para a criao de tipos de dados complexos.
Como exemplo, imagine que os nossos livros so divididos em grupos, consistindo de um
"dicionrio" e um livro de "literatura".
Ex.:

O programa cria uma estrutura de etiqueta grupo, que consiste de duas outras do tipo livro.

22

FACENS Linguagem de Programao MDULO 2 Prof. Andra


struct livro {
char titulo[30];
int
regnum;
};
struct grupo {
struct livro
struct livro
};
main()
{
struct grupo

dicionario;
literatura;

grupo1 = {

{"Aurelio",134},
{"Iracema",321}

};
printf("\n Dicionario:\n");
printf("Titulo: %s \n", grupo1.dicionario.titulo);
printf("N do registro: %3i \n", grupo1.dicionario.regnum);
printf("\n Literatura:\n");
printf("Titulo: %s \n", grupo1.litertura.titulo);
printf("N do registro: %3i \n", grupo1.literatura.regnum);
}// main
Vamos analisar alguns detalhes deste programa:
Primeiro, declaramos uma varivel estrutura grupo1, do tipo grupo, e inicializamos esta
estrutura com os valores mostrados. Quando uma matriz de vrias dimenses inicializada,
usamos chaves dentro de chaves, do mesmo modo inicializamos estruturas dentro de
estruturas.
Segundo, note como acessamos um elemento da estrutura que parte de outra estrutura. O
operador ponto usado duas vezes:
grupo1.dicionario.titulo
Isto referencia o elemento titulo da estrutura dicionario da estrutura grupo1.
Logicamente este processo no pra neste nvel, podemos ter uma estrutura dentro de outra dentro
de outra.
Tais construes aumentam o nome da varivel, podendo descrever surpreendentemente o seu
contedo.

6.13 - Matrizes de Estruturas


Por exemplo, em um programa que mantenha uma lista de emails e nmeros de telefones, voc
poderia definir uma estrutura que armazenasse um nome, um email e um nmero:
struct entrada{
char nome[10];
char email[12];
char fone[8];
};

23

FACENS Linguagem de Programao MDULO 2 Prof. Andra


Porm, uma lista telefnica composta de vrios nomes, emails e nmeros. Ento, precisamos
de uma matriz de estruturas. Depois que a estrutura estiver definida, podemos declarar uma matriz da
seguinte maneira:
struct entrada

lista[1000];

Esta instruo declara uma matriz chamada lista que contm 1000 elementos. Cada elemento
uma estrutura do tipo entrada e identificada por um ndice, como em qualquer outra matriz. Cada
uma dessas estruturas, por sua vez, contm trs elementos, cada um dos quais uma matriz do tipo
char. Esse esquema relativamente complexo ilustrado abaixo:
lista[0].nome[0]
lista[0]

lista[0].nome
lista[0].email
lista[0].fone

lista[1]

lista[1].nome
lista[1].email
lista[1].fone

lista[999]

lista[999].nome
lista[999].email
lista[999].fone
lista[999].fone[2]

Da mesma forma que podemos atribuir o valor de uma varivel estrutura a outra
lista[5] = lista[1]
Podemos transferir dados entre os elementos individuais das matrizes que so membros
das estruturas:
lista[5].fone[1] = lista[2].fone[3];
Esta instruo move o segundo caractere do nmero de telefone armazenado em lista[5] para a
quarta posio do nmero de telefone armazenado em lista[2]. (No se esquea que os ndices
comeam em 0).

24

FACENS Linguagem de Programao MDULO 2 Prof. Andra


6.14 - Inicializando Estruturas Complexas
No caso de uma estrutura que contenha estruturas como membros, os valores de inicializao
devem ser listados em ordem.
Ex.:
struct cliente {
char firma[20];
char contato[25];
};
struct venda {
struct cliente comprador;
char item[20];
float quantia;
} minhavenda = { { "Acme Industrias", "George Adams"},
"meias",
1000 };

Estas instrues realizam as seguintes inicializaes:


o membro da estrutura minhavenda.comprador.firma inicializado com o string "Acme Industrias".
o membro da estrutura minhavenda.comprador.contato inicializado com o string "George Adams".
o membro da estrutura minhavenda.item inicializado com o string "meias".
o membro da estrutura minhavenda.quantia inicializado com o valor 1000.
No caso de matrizes de estruturas. Os dados de inicializao sero aplicados, pela ordem, s
estruturas da matriz.
Ex. - declaramos uma matriz de estruturas do tipo venda e inicializamos os dois primeiros elementos
da matriz (ou seja, as duas primeiras estruturas):
struct cliente {
char firma[20];
char contato[25];
};
struct venda {
struct cliente comprador;
char item[20];
float quantia;
};
struct venda A1990[100] = {
{ { "Acme Indstrias", "George Adams" },
"meias",
1000
}
{ { "Wilson & Cia", "Edi Wilson" },
"brincos",
290
}
};
25

FACENS Linguagem de Programao MDULO 2 Prof. Andra

o membro da estrutura A1990[0].comprador.firma ser inicializado com o string "Acme Industrias".


o membro da estrutura A1990[0].comprador.contato ser inicializado com o string "George Adams".
o membro da estrutura A1990[0].item ser inicializado com o string "meias".
o membro da estrutura A1990[0].quantia ser inicializado com valor 1000.

o membro da estrutura A1990[1].comprador.firma ser inicializado com o string "Wilson & Cia".
o membro da estrutura A1990[1].comprador.contato ser inicializado com o string "Edi Wilson".
o membro da estrutura A1990[1].item ser inicializado com o string "brincos".
o membro da estrutura A1990[1].quantia ser inicializado com valor 290.

6.15 Exerccios Propostos


1. Fazer um programa para Sistema de Conta Bancria este programa se destina a controlar as
contas de 10 clientes.
[1] Cadastro - receber os valores digitados pelo usurio. Apenas um registro cadastrado por vez.
[2] Depsito - o acesso deve ser feito atravs do n de conta corrente. Buscar o registro, mostrar o
nome do cliente e o saldo para simples conferncia, pedir o valor do depsito, fazer as alteraes e
apresentar na tela o saldo atualizado.
[3] Retirada - o acesso deve ser feito atravs do n de conta corrente. Buscar o registro, mostrar o
nome do cliente e o saldo para simples conferncia, pedir o valor da retirada, fazer as alteraes se
possvel (a retirada s ser permitida, se houver saldo suficiente) e apresentar na tela o saldo
atualizado.
struct cliente{
char nome[30];
int conta;
float saldo;
};
2. Fazer um programa para Dirio Eletrnico este programa se destina a controlar as notas e a
mdia de 10 alunos.
[1] Cadastro - receber os valores digitados pelo usurio, inicialmente notas e mdia=0. Apenas um
registro cadastrado por vez.
[2] Controle de Notas - o acesso deve ser feito atravs do RA. Buscar o registro, mostrar o nome do
aluno para simples conferncia, fazer as alteraes das notas, calcular a mdia e apresentar na tela as
notas e a mdia.
struct aluno{
char nome[80];
char RA[7];
float nota[2];
float media;
};

//notas de provas considerar 2 provas


//mdia aritmtica das provas

26

FACENS Linguagem de Programao MDULO 2 Prof. Andra

7. ESTRUTURAS COMPLEXAS
7.1 - Estruturas e Ponteiros
Podemos declarar ponteiros que apontem para estruturas e tambm usar ponteiros como
membros de estruturas, ou ambos.

7.2 - Ponteiros para Estruturas


Os ponteiros para estruturas geralmente so usados para passar uma estrutura como argumento
para uma funo. Alm disso, os ponteiros para estruturas tambm so usados em um mtodo muito
poderoso de armazenagem de dados conhecido como listas encadeadas.
Como um programa pode criar e usar ponteiros para estruturas? Em primeiro lugar, devemos
definir uma estrutura.
Ex.:
struct pea {
int
numero;
char nome[10];
};
A seguir, devemos declarar um ponteiro para o tipo peca.
struct pea
O

*p_pea;

operador de indireo (*) na declarao significa que p_pea um ponteiro para o tipo pea,
no uma instncia da estrutura do tipo pea.

O ponteiro j pode ser inicializado? No, porque a estrutura pea foi definida, mas nenhuma
instncia dessa estrutura foi declarada ainda. Lembre-se que a declarao, no a definio, que
reserva espao na memria para a armazenagem de um objeto de dados. Como o ponteiro precisa de
um endereo na memria para o qual possa apontar, teremos que declarar uma instncia do tipo pea
antes que algo possa apontar para ela.
Portanto, esta a declarao:
struct pea

produto;

Agora j podemos inicializar o ponteiro:


p_pea = &produto;

Essa instruo atribui o endereo de produto a p_pea. A relao entre uma estrutura e um
ponteiro para essa estrutura mostrada na figura abaixo:

27

FACENS Linguagem de Programao MDULO 2 Prof. Andra


produto.numero

produto.nome[ ]

p_pea
Um ponteiro para uma estrutura aponta para o primeiro byte dessa estrutura.
Agora que j temos um ponteiro apontando para a estrutura produto, podemos acessar os
membros de uma estrutura usando um ponteiro de 3 maneiras:

7.2.1 - Operador de Acesso Indireto


o mais comum. Que consiste dos smbolos
->
(um sinal de menos seguido do
smbolo de "maior que" - quando estes dois caracteres so usados juntos desta maneira, a linguagem C
os interpreta como um nico operador, no dois). O smbolo colocado entre o nome do ponteiro e o
nome do membro da estrutura.
Ex.:
p_pea->numero

/* acessa o membro nmero da estrutura produto */

7.2.2 - Operador de Indireo (*)


Ex.:
p_pea um ponteiro para a estrutura pea; portanto,
*p_pea refere-se a produto
Devemos aplicar o operador ponto (.) para acessarmos elementos individuais de produto.
(*p_pea).numero = 100;
O

/* atribui o valor 100 a produto.numero */

item p_pea deve estar entre parnteses porque o operador (.) tem maior precedncia que o
operador (*).

7.2.3 - Nome da Estrutura


Ex.:
produto.numero

28

FACENS Linguagem de Programao MDULO 2 Prof. Andra


Portanto, sendo p_pea um ponteiro para a estrutura pea, todas estas expresses so equivalentes:
produto.numero
(*p_pea).numero
p_pea->numero

7.3 - Ponteiros e Matrizes de Estruturas


Tanto as matrizes de estruturas como os ponteiros para estruturas so ferramentas de
programao extremamente poderosas. Podemos tambm combinar esses dois mtodos usando
ponteiros para acessar estruturas que so elementos de matrizes.
Para ilustrar isso, vamos usar esta definio de estrutura de um exemplo anterior:
struct pea {
int
numero;
char nome[10];
};
Depois que a estrutura foi definida, podemos definir uma matriz do tipo pea, chamada dados:
struct pea

dados[100];

A seguir, podemos declarar um ponteiro para o tipo pea e inicializ-lo para apontar para a
primeira estrutura contida na matriz:
struct pea *p_pea;
p_pea = &dados[0];
Lembrando que o nome de uma matriz sem os colchetes um ponteiro para o primeiro
elemento dessa matriz. Portanto, a segunda linha tambm poderia ter sido escrita da seguinte forma:
p_pea = dados;
Agora j temos uma matriz de estruturas do tipo pea e um ponteiro para o primeiro elemento
dessa matriz (ou seja, para a primeira estrutura da matriz). Poderamos, por exemplo, imprimir o
contedo desse primeiro elemento usando a instruo:
printf("%i
scanf(%i,

%s", p_pea->numero, p_pea->nome);


&(p_pea->numero);

E se quisssemos imprimir todos os elementos da matriz? Nesse caso, provavelmente


usaramos um loop for. Para acessar os membros usando notao de ponteiros, teramos que alterar o
ponteiro p_pea para que, a cada iterao do loop, ele apontasse para o prximo elemento da matriz
(ou seja, para a prxima estrutura contida na matriz).
29

FACENS Linguagem de Programao MDULO 2 Prof. Andra


Para isso, a aritmtica de ponteiros da linguagem C pode lhe ser til. O operador unrio de
incremento (++) tem um significado especial quando aplicado a um ponteiro, passando a significar
"incrementar o ponteiro com um valor equivalente ao tamanho do objeto para o qual ele est
apontando". Em outras palavras, se voc tem um ponteiro ptr que aponta para um objeto de dados do
tipo obj, a instruo:
ptr++;
tem o mesmo efeito de:
ptr += sizeof (obj);
Os elementos de uma matriz sempre so armazenados seqencialmente na memria. Se um
ponteiro estiver apontando para o elemento n de uma matriz, o uso do operador (++) para incrementlo far com que ele passe a apontar para o elemento n+1. Isto ilustrado na figura abaixo, que mostra
uma matriz chamada x[ ] que consiste de elementos de quatro bytes (cada elemento pode ser, por
exemplo, uma estrutura contendo dois membros do tipo char, cada um dos quais ocupa dois bytes). O
ponteiro ptr foi inicializado para apontar para x[0] ; cada vez que incrementado, ptr passa a apontar
para o prximo elemento da matriz.
X[0]
1001

1
0
0
1

1002

x[1]
1003

ptr++

1004

1005

1
0
0
5

1006

x[2]
1007

1008

ptr++

1009

1010

1011

1012 .....

1
0
0
9

Isto significa que o seu programa pode avanar atravs de uma matriz de estruturas (ou, para
ser exato, atravs de uma matriz de qualquer tipo) simplesmente incrementando um ponteiro. Este tipo
de notao geralmente mais fcil de usar e mais conciso do que o uso de subscritos de matrizes para
realizar a mesma tarefa.
Ex. - acessa elementos sucessivos de uma matriz atravs do incremento de um ponteiro.
#include <stdio.h>
#define MAX
4
struct pea {
int numero;
char nome[10];
};
main()
{
struct pea
*p_pea,

int

dados[MAX] = {1, "camisa",


2, "cala",
3, "gravata",
4, "casaco"
};

contagem;
30

FACENS Linguagem de Programao MDULO 2 Prof. Andra


p_pea = dados;
// inicializa o ponteiro para o primeiro elemento da matriz
for (contagem = 0; contagem < MAX; contagem++)
{
printf("\n No endereo %u : %i
%s", p_pea, p_peca->numero, p_pea->nome ) ;
p_pea++;
}
}// main
Teremos como sada, por exemplo:
No endereo 96: 1 camisa
No endereo 120: 2 cala
No endereo 144: 3 gravata
No endereo 168: 4 casaco
Inicialmente, o programa declara e inicializa uma matriz de estruturas chamada dados. A seguir,
definido um ponteiro chamado p_pea para apontar para uma estrutura do tipo peas. A primeira
tarefa da funo main( ) inicializar o ponteiro p_pea para que ele aponte para a matriz dados
declarada anteriormente. A seguir, todos os elementos dessa matriz so impressos na tela usando um
loop for que incrementa o ponteiro a cada interao. O programa exibe tambm o endereo de cada
elemento da matriz.
Observando os endereos mostrados, percebemos que todos os incrementos sero feitos em
quantidades iguais, correspondendo ao tamanho da estrutura peas (na maioria dos sistemas, esse
incremento ser de 24 bytes). Isto ilustra claramente o fato de que o incremento de um ponteiro feito
com um valor igual ao tamanho do objeto de dados para o qual ele est apontando.

7.4 - Passando Estruturas como Argumentos para Funes


Como qualquer outro tipo de dados, uma estrutura pode ser passada como um argumento para
uma funo. O programa abaixo mostra como isso feito.
Ex.:
#include <stdio.h>
struct dados{
float quantia;
char nome[80];
};
void

print_reg (struct dados

x);

main( )
{
struct dados reg;
printf("Digite o nome e o sobrenome do doador: ");
scanf("%s
%s", reg.nome, reg..snome);
printf("\n Digite a quantia doada: ");
scanf("%f", &reg.quantia);
print_reg( reg );
}// main

31

FACENS Linguagem de Programao MDULO 2 Prof. Andra


void print_reg(struct dados
x)
{
printf("\O doador %s doou R$%.2f.", x.nome, x.quantia);
}
Teremos como sada na tela:
Digite o nome e o sobrenome do doador: Carlos Silva
Digite a quantia doada: 1000.00
O doador Carlos Silva doou R$1000.00.
O prottipo da funo dever receber a estrutura, portanto devemos incluir os parmetros
adequados. No caso, uma estrutura do tipo dados. As mesmas informaes so repetidas no
cabealho da funo. Ao chamarmos a funo, temos que informar o nome da instncia dessa estrutura
- no caso, reg. Isso tudo. Passar uma estrutura para uma funo no muito diferente de passar uma
varivel simples. Alternativamente, podemos passar uma estrutura para uma funo informando o seu
endereo (ou seja, passando um ponteiro que aponte para a estrutura).
De fato, esta era a nica maneira de usarmos uma estrutura como argumento nas verses mais
antigas da linguagem C. Isso j no necessrio, mas possvel encontrarmos programas mais antigos
que ainda usam esse mtodo. Ao passarmos um ponteiro como argumento para uma funo, teremos
que usar o operador de acesso indireto (->) para acessarmos membros da estrutura de dentro da funo.
Ex. Novamente, usaremos o programa de livros, onde uma funo obter informaes dos livros pelo
usurio e outra ir imprimi-las.
#include <stdio.h>
#include <stdlib.h>
typedef struct 1ivro {
char titulo[30];
int regnum;
}livro;
livro
void

novonome();
listar (livro liv);

main( )
{
livro livro1, livro2;
livro1 = novonome();
livro2 = novonome();
listar(livro1);
listar(livro2);
} // main

// funo do tipo struct livro chamada novonome


// funo void, cujo parmetro do tipo struct livro

// varivel estrutura chamada livro1, livro2


// livro1 ir receber o retorno da funo novonome
// livro2 ir receber o retorno da funo novonome

32

FACENS Linguagem de Programao MDULO 2 Prof. Andra


livro novonome()
{
char numstr[8];
livro livr;

// varivel estrutura chamada livr

printf("\n Novo livro \n Digite titulo: ");


gets(livr.titulo);
printf("Digite o numero do registro (3 dgitos): );
gets(numstr);
livr.regnum = atoi(numstr);
return(livr);
}// novonome
void listar (livro
liv)
{
printf("\n Livro: \n");
printf("Titulo: %s ", liv.titulo);
printf("\n N do registro: %3i", liv.regnum);
} // listar
Visto que as duas funes, como tambm o programa main(), devem conhecer a estrutura livro,
ela deve ser definida antes da main().
As funes main(), novonome() e listar() declaram internamente suas prprias variveis
estrutura, chamadas livro1 e livro2, livr e liv.
A funo listar() recebe uma cpia da estrutura e a coloca num endereo conhecido somente
por ela; no a mesma estrutura declarada em main().
A funo novonome() chamada pelo programa principal para obter informaes do usurio
sobre os 2 livros. Esta funo guarda as informaes em uma varivel interna, livr, e retorna o valor
desta varivel para o programa principal usando o comando return, exatamente como faria para
devolver uma simples varivel. A funo novonome( ) deve ser declarada como sendo do tipo struct
livro, visto que ela retorna um valor deste tipo.
O programa principal atribui o valor retornado por novonome() varivel estrutura livro1 e
livro2. Finalmente main() chama a funo listar() para imprimir os valores de livro1 e livro2, passando
os valores destas duas estruturas para a funo como variveis.
A funo listar() atribui estes valores varivel estrutura interna liv e acessa os elementos
individuais desta estrutura para imprimir seus valores.

7.5 Estruturas e Alocao Dinmica


Para alocarmos memria dinamicamente na main, devemos declarar um ponteiro e utilizar
malloc(), calloc() ou realloc(). Porm, quando utilizamos funo, devemos lembrar que a memria no
pode ser conhecida apenas na funo, mas tambm na main. Portanto, devemos declarar um ponteiro
na main e a funo pode ser feita de 2 formas:

33

FACENS Linguagem de Programao MDULO 2 Prof. Andra

Chamada por Referncia devemos passar o endereo do ponteiro declarado na main,


portanto, a funo receber como parmetro ponteiro para ponteiro.
Chamada por Valor s conseguimos trabalhar dessa forma, se a funo retornar o
endereo alocado para o ponteiro declarado na main, permitindo assim, o acesso deste
memria alocada. Caso contrrio o ponteiro na main continuar NULL e ao sairmos da funo
perdemos a referncia da memria alocada. Lembre-se que as variveis (inclusive ponteiro)
declaradas dentro da funo, deixam de existir assim que a funo termina.

Verso para Alocao feita na main( )


#include <stdio.h>
#include <stdlib.h>
typedef struct 1ivro {
char titulo[30];
int regnum;
}livro;
main( )
{
livro *ptr=NULL;
if((ptr = (livro *) realloc(ptr, 10 * sizeof(livro))) == NULL)
{
printf(Erro na alocao);
exit(1);
}
}//main

// aloca 10 elementos

Verso utilizando Chamada por Referncia


#include <stdio.h>
#include <stdlib.h>
typedef struct 1ivro {
char titulo[30];
int regnum;
}livro;
void aloca(livro **p, int tam);

//passa o endereo do ponteiro declarado na main

main( )
{
livro *ptr=NULL;
aloca(&ptr, 10);
}//main

//chamada por referencia

34

FACENS Linguagem de Programao MDULO 2 Prof. Andra


void aloca(livro **p, int tam)
{
if((*p=(livro*)realloc(*p, tam*sizeof(livro)))== NULL)
{
printf("Erro de alocacao");
exit(1);
}
}//aloca
Verso utilizando Chamada por Valor com RETORNO do endereo alocado
#include <stdio.h>
#include <stdlib.h>
typedef struct 1ivro {
char titulo[30];
int regnum;
}livro;
livro* aloca(livro *p, int tam);

//retorna o endereo da memria alocada

main()
{
livro *ptr=NULL;
ptr = aloca(ptr, 10);
}//main

//chamada por valor

livro* aloca(livro *p, int tam)


{
if((p=(livro*)realloc(p, tam*sizeof(livro)))== NULL)
{
printf("Erro de alocacao");
exit(1);
}
return p;
}//aloca

7.6 Exerccios Propostos


1. Dado a estrutura abaixo, implemente uma rotina de cadastro, deve-se consultar o usurio para
continuar. O registro deve ser gerado automaticamente pelo sistema. Utilizar alocao dinmica e
ponteiros para a estrutura.
struct agenda
{
int reg;
char nome[80];
float nota;
};
35

FACENS Linguagem de Programao MDULO 2 Prof. Andra


2. Fazer um programa para Sistema de Conta Bancria este programa se destina a controlar as
contas de clientes. Consultar o usurio para continuar. Utilizar alocao dinmica e ponteiros
para a estrutura.
[1] Cadastro - receber os valores digitados pelo usurio. Apenas um registro cadastrado por vez.
[2] Depsito - o acesso deve ser feito atravs do n de conta corrente. Buscar o registro, mostrar o
nome do cliente e o saldo para simples conferncia, pedir o valor do depsito, fazer as alteraes e
apresentar na tela o saldo atualizado.
[3] Retirada - o acesso deve ser feito atravs do n de conta corrente. Buscar o registro, mostrar o
nome do cliente e o saldo para simples conferncia, pedir o valor da retirada, fazer as alteraes se
possvel (a retirada s ser permitida, se houver saldo suficiente) e apresentar na tela o saldo
atualizado.
struct cliente{
char nome[30];
int conta;
float saldo;
};
3. Fazer um programa para Dirio Eletrnico este programa se destina a controlar as notas e a
mdia dos alunos. Consultar o usurio para continuar. Utilizar alocao dinmica e ponteiros
para a estrutura.
[1] Cadastro - receber os valores digitados pelo usurio, inicialmente notas e mdia=0. Apenas um
registro cadastrado por vez.
[2] Controle de Notas - o acesso deve ser feito atravs do RA. Buscar o registro, mostrar o nome do
aluno para simples conferncia, fazer as alteraes das notas, calcular a mdia e apresentar na tela as
notas e a mdia.
struct aluno{
char nome[80];
char RA[79];
float nota[2];
float media;
};

//notas de provas considerar 2 provas


//mdia aritmtica das provas

4. Fazer um programa para Controle de Hotel - este programa se destina a controlar o check-in
(cadastro de hspedes) de um hotel. O hotel possui 15 quartos. Utilizar alocao dinmica e
ponteiros para a estrutura.
[1] Check-in - alocar dinamicamente espao, receber os valores digitados pelo usurio, se o hspede
no tiver acompanhantes atribuir categoria Solteiro, caso contrrio Familiar, buscar o nmero do
quarto disponvel, de acordo com a categoria na estrutura quartos. Apenas um hspede cadastrado
por vez. No esquecer de atualizar o quarto da estrutura quartos para Ocupado.
[2] Check-out encerra a estadia e apresenta o relatrio, de acordo com o quarto. Apenas um registro
acessado por vez, buscar e mostrar o nmero do quarto, o nome do hspede, quantidade de
acompanhantes, a categoria (Solteiro ou Familiar,o tempo de permanncia em dias e o valor a ser pago.
[3] Fim
36

FACENS Linguagem de Programao MDULO 2 Prof. Andra


Dica:

No check-in - no esquecer de verificar se na estrutura hospede h um espao vago (cujo


quarto = -1), se houver o novo hspede dever ser ali armazenado, caso contrrio, acrescentar
no final da estrutura.
struct hospede{
int quarto;
char nome[80];
int acompanhante;
char categoria;
int dias;
};
struct quarto{
int num;
char categoria
char status
};

// nmero do quarto
// quantidade de acompanhantes
// [S]olteiro / [F]amiliar
// tempo de permanncia em dias

// nmero do quarto
// [S]olteiro / [F]amiliar
// [L]ivre / [O]cupado

Categoria de quarto:
[S]olteiro diria R$ 85,00 por pessoa
[F]amiliar diria R$ 45,00 por pessoa

37