Buscar

LINGUAGEM E TECNICA DE PROGRAMAÇÃO

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 44 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 44 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 44 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

392
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Unidade VI
Nesta unidade, abordaremos definitivamente a linguagem C. As noções de pseudocódigo e 
de todas as suas estruturas já foram ensinadas e sempre deverão ser usadas no desenvolvimento 
de programas.
Passaremos a estudar técnicas e rotinas consagradas, que serão um atalho no desenvolvimento de 
programas mais complexos.
Para o completo entendimento, necessitaremos entender como as linguagens, em especial a 
linguagem C, administram a memória RAM, o espaço disponível para os nossos programas serem 
executados.
6 AlocAção dinâmicA dA memóriA
Ao declarar um vetor, para dimensioná-lo, era necessário saber de antemão quantos elementos 
iriam compô-lo. Tínhamos de prever o número máximo de elementos no vetor durante o 
processo da codificação. O pré-dimensionamento do vetor é um fator que limita a programação. 
Uma solução seria superdimensionar o vetor para tentar contornar essa falta de elementos 
livres durante a execução do programa, mas isso acarreta um desperdício de memória, o que é 
inaceitável em diversas aplicações, como aplicativos portáteis, em que sempre estamos sujeitos 
a ter falta de memória.
A linguagem C oferece meios de utilizar e racionalizar o uso da memória durante a execução do 
programa, ou seja, podemos alocar memória dinamicamente. Esse recurso permite ao programa alocar 
elementos ou registros dinamicamente, sem desperdício de memória.
6.1 o uso da memória
Basicamente, existem três maneiras de reservarmos espaço de memória para o armazenamento de 
informações, sem o rigor técnico.
A primeira maneira é por meio do uso de variáveis globais (e estáticas). Nessa categoria de 
variáveis, o espaço reservado para uma variável existirá enquanto o programa estiver sendo 
executado.
A segunda maneira é usando variáveis locais. Nessa categoria, o espaço na memória existe apenas 
no período em que a função que declarou a variável está sendo executada, sendo liberado assim que a 
execução da função terminar. Como consequência, a função que chama não pode fazer referência ao 
espaço local da função chamada. As variáveis globais ou as locais podem ser simples ou vetores. Para os 
393
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
vetores, é necessário informar o número máximo de elementos, caso contrário o compilador não terá a 
informação sobre o tamanho do espaço a ser reservado.
A terceira maneira de reservar a memória é solicitar ao programa que aloque dinamicamente um 
espaço na memória durante sua execução. Esse espaço permanece reservado até que seja liberado 
explicitamente pelo programa, por meio de comando específico.
Para o entendimento do processo de uso da memória, vamos fazer uma simulação da execução de 
um programa.
1. Vamos supor que esta seja uma memória RAM de um computador sem nenhum programa sendo 
executado:
RAM 
Figura 442 – Memória RAM sem programa
2. Ao colocarmos um programa para ser executado, o sistema operacional carregará o código 
compilado na memória:
394
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
RAM 
Programa
Figura 443 – Colocação do programa na memória
3. Uma vez com o código na memória, o sistema passa a ser comandado pelo programa. 
A primeira etapa é reservar o espaço para as constantes e as variáveis globais, pois essas são 
estáticas, ou seja, não serão criadas constantes nem variáveis globais durante a execução do resto 
do programa:
395
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
RAM 
Programa
Variáveis globais e constantes
Figura 444 – Com o código na memória, o programa passa a comandar o sistema.
4. Cada vez que uma determinada função é chamada, o sistema reserva o espaço necessário para as 
variáveis locais da função. Simultaneamente, a pilha do controle da chamada das funções armazena a 
sequência de chamada e o estado geral das memórias operacionais. Conforme as funções são chamadas, 
a memória livre cresce, e a pilha é atualizada. Quando as funções são encerradas, o sistema consulta na 
pilha o ponto em que a função foi chamada, retornando o programa nesse ponto e liberando o espaço 
das variáveis e da pilha criados dinamicamente:
396
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
RAM 
Programa
Variáveis locais
Memória livre
Pilha
Variáveis globais e constantes
Figura 445 – Comportamento do sistema quando as funções são chamadas e encerradas
6.2 Ponteiro de variáveis
Na cidade de São Paulo existe um edifício famoso, o prédio da Gazeta, diante do qual, sempre que 
há uma comemoração da conquista de um campeonato, qualquer que seja o time paulista, a torcida 
se concentra, a fim de festejar. Vamos supor que você não seja da cidade de São Paulo, gostaria que 
comemorar o campeonato do seu time e queira chegar ao prédio da Gazeta a partir de um terminal de 
ônibus, de uma estação de trem ou de um aeroporto. Indo de táxi, pode pedir ao taxista para levá-lo ao 
prédio da Gazeta, ou então para a Avenida Paulista, nº 900.
Pelo que vimos até agora, cada vez que uma variável é declarada, um espaço é alocado na 
memória para armazenar valores. Tecnicamente, é feito mais do que a simples reserva. O programa 
tem uma tabela, em que armazena o nome da variável, o endereço e o tipo de valor que será 
armazenado. Assim, ao escrevermos int a;, o programa reserva um espaço, normalmente de 4 
bytes, por ser inteiro, no primeiro espaço livre da memória que encontrar. Em seguida, cria uma 
linha em uma tabela, na qual armazena o endereço e o tipo associado à variável criada nesse 
momento.
Em muitas ocasiões, seria interessante poder acessar o conteúdo de um local da memória de outras 
maneiras que não fossem pelo nome ou pelo endereço de memória, por exemplo, da mesma maneira 
que o prédio da Gazeta pode ser localizado pelo seu endereço ou pelo seu nome.
397
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
A linguagem C tem uma maneira especial de uma variável armazenar endereços. Essa variável se chama 
variável ponteiro, ou, simplesmente, ponteiro. A declaração de uma variável é feita da seguinte forma:
<tipo> *nome;
Por exemplo:
 int *p;
O programa reserva um espaço na memória para uma variável chamada p, que irá guardar um 
endereço, e esse endereço armazenado conterá uma informação do tipo inteiro. O símbolo * identifica 
que uma variável é do tipo ponteiro.
Para acessar os endereços de memória, a linguagem oferece dois operadores unários:
•	 & (“endereço de”), aplicado a variáveis, resulta no endereço da posição da memória reservada para a variável;
•	 * (“conteúdo de”), aplicado a variáveis do tipo ponteiro, acessa o conteúdo do endereço de memória 
armazenado pela variável ponteiro.
Vamos analisar o seguinte trecho de programa:
int a;
int *p;
a=5;
p = &a;
*p = 6;
/*variável inteiro */
int a;
/*variável ponteiro p/ inteiro */
int *p;
/* a recebe o valor 5 */
a=5;
/* p recebe o endereço de a
(diz-se p aponta para a) */
p = &a;
/* conteúdo de p recebe o valor 6 */
*p = 6;
Memória RAM
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
398
Re
visã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Variáveis
Figura 446 – Memória RAM livre
Inicialmente, a memória RAM (nesse caso, uma memória fictícia) está livre, e o conteúdo pode ser 
qualquer sobra de outros programas que utilizaram esse espaço.
/*variável inteiro */
int a;
/*variável ponteiro p/ inteiro */
int *p;
/* a recebe o valor 5 */
a=5;
/* p recebe o endereço de a
(diz-se p aponta para a) */
p = &a;
/* conteúdo de p recebe o valor 6 */
*p = 6;
Memória RAM
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
Variáveis
a 101 int
Figura 447 – Reserva de bytes e criação de tabela
O programa reserva quatro bytes, em que serão armazenados os valores de a. Ao mesmo tempo, cria 
uma tabela com as referências da variável criada.
/*variável inteiro */
int a;
/*variável ponteiro p/ inteiro */
int *p;
/* a recebe o valor 5 */
a=5;
/* p recebe o endereço de a
(diz-se p aponta para a) */
p = &a;
/* conteúdo de p recebe o valor 6 */
*p = 6;
399
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Memória RAM
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
Variáveis
a 101 int
*p 105 int
Figura 448 – Reserva de espaço para valores de p e atualização da tabela
O programa reserva o espaço correspondente a um endereço de memória em que serão armazenados 
os valores de uma variável ponteiro p e atualiza a tabela.
/*variável inteiro */
int a;
/*variável ponteiro p/ inteiro */
int *p;
/* a recebe o valor 5 */
a=5;
/* p recebe o endereço de a
(diz-se p aponta para a) */
p = &a;
/* conteúdo de p recebe o valor 6 */
*p = 6;
Memória RAM
101 102 103 104 105 106 107 108 109 110
5
111 112 113 114 115 116 117 118 119 120
Variáveis
a 101 int
*p 105 int
Figura 449 – Atribuição de valor à variável a
/*variável inteiro */
int a;
/*variável ponteiro p/ inteiro */
int *p;
/* a recebe o valor 5 */
a=5;
/* p recebe o endereço de a
(diz-se p aponta para a) */
p = &a;
/* conteúdo de p recebe o valor 6 */
*p = 6;
400
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Memória RAM
101 102 103 104 105 106 107 108 109 110
5 101
111 112 113 114 115 116 117 118 119 120
Variáveis
a 101 int
*p 105 int
Figura 450 – O endereço é passado de a para p
A variável p recebe endereço de a (note o operador unário &), passando a apontar para o endereço onde está a.
/*variável inteiro */
int a;
/*variável ponteiro p/ inteiro */
int *p;
/* a recebe o valor 5 */
a=5;
/* p recebe o endereço de a
(diz-se p aponta para a) */
p = &a;
/* conteúdo de p recebe o valor 6 */
*p = 6;
Memória RAM
101 102 103 104 105 106 107 108 109 110
6 101
111 112 113 114 115 116 117 118 119 120
Variáveis
a 101 int
*p 105 int
Figura 451 – O valor 6 é atribuído à variável a
Aqui se encontra a grande diferença: no endereço apontado por p, receberá o valor 6, ou seja, a 
variável a passará a conter o valor 6.
Nesse exemplo temos as duas maneiras pelas quais é possível trabalhar com memória em C: uma por 
meio do nome da variável, e a outra, pelo endereço desta.
6.3 Passagem de valores por valor e por referência
Quando estudamos funções vimos que, quando passamos informações para dentro de uma função, 
fazemos isso por meio de parâmetros. Também foi dito que uma função é aquela que devolve um e 
apenas um valor, ou seja, não devolve mais de um valor. O uso de ponteiros amplia a possibilidade de 
utilização dos parâmetros e solução de problemas de retornos múltiplos.
401
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Dizemos que há uma passagem de parâmetros por valor quando conteúdos (e não endereços) são 
passados para as funções.
No exemplo a seguir, os valores de a e b são passados para a função troca.
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Figura 452 – Saída mostrando a passagem de parâmetros por valor
O resultado de a é 7 e o de b é 5, pois efetivamente as variáveis a e b são locais da função main( ).
Quando os parâmetros passados são endereços, dizemos que foram passados por referência, como 
no exemplo a seguir.
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
402
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Figura 453 – Saída do programa passando parâmetros por referência
Apesar de os programas serem praticamente idênticos, o resultado é bem diferente, pois o mecanismo 
de trabalho foi bem diverso.
Exemplo de aplicação
Para entender o que acontece em cada um dos casos, vamos fazer o teste de mesa nos próprios 
códigos.
•	 Passagem	por	valor
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
Variáveis:main
Figura 454 – Início do programa
403
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118 119 120
Variáveis:main
a 101 int
b 105 int
Figura 455 – Criação das variáveis a e b
As variáveis a e b da função são criadas e inicializadas. Nesse momento, o programa reserva os 
espaços na memória RAM e atualiza a tabela das variáveis da função main( ).
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
404
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118 119 120
7 5
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
a 109 int
b 113 int
Figura 456 – Reserva de memória para as próximas variáveis e criação de tabela para as variáveis locais
Ao encontrar a chamada para a função troca, o programa continua reservando espaço da memória 
para as variáveis que forem aparecendo e cria uma nova tabela para as suas variáveis locais, armazenando 
os parâmetros de entrada. Em seguida, passa a executar a função troca.
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118119 120
7 5
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
a 109 int
b 113 int
temp 117 int
Figura 457 – O programa cria a variável temp
405
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118 119 120
7 5 7
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
a 109 int
b 113 int
temp 117 int
Figura 458 – Temp recebe o conteúdo da variável a da função troca
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
406
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118 119 120
5 5 7
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
a 109 int
b 113 int
temp 117 int
Figura 459 – A variável a recebe o conteúdo da variável b da função troca
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118 119 120
5 7 7
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
a 109 int
b 113 int
temp 117 int
Figura 460 – A variável b recebe conteúdo de temp
A variável b recebe o conteúdo da variável temp da função troca, e o programa retorna para o ponto 
de chamada da função main( ).
407
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
#include<stdio.h>
void troca(int a, int b){
 int temp;
 temp=a;
 a=b;
 b=temp;
}
void main(){
 int a=7,b=5;
 troca(a,b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118 119 120
5 7 7
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
a 109 int
b 113 int
temp 117 int
Tela:
a=7
b=5
Figura 461 – Exibição dos conteúdos de a e b da função main( )
A função main( ) exibe os conteúdos das variáveis a e b da própria função main( ), aqueles valores 
que estão nos endereços da tabela Variáveis:main.
Passagem por referência
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
408
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Memória RAM
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
Variáveis:main
Figura 462 – Início do programa
O programa começa com a memória vazia, executando a função main( ).
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5
111 112 113 114 115 116 117 118 119 120
Variáveis:main
a 101 int
b 105 int
Figura 463 – Criação e inicialização das variáveis a e b
As variáveis a e b da função são criadas e inicializadas. Nesse momento, o programa reserva os espaços na 
memória RAM e atualiza a tabela das variáveis da função main( ). Até esse ponto, os dois programas são iguais.
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
409
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5 &101
111 112 113 114 115 116 117 118 119 120
&105
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
*a 109 int
*b 111 int
Figura 464 – Recebimento dos ponteiros
Na chamada da função é que começam as diferenças. A função troca recebe dois ponteiros do tipo 
inteiro, lembrando sempre que ponteiros armazenam endereços, e não valores absolutos. Na passagem 
de parâmetro, são endereços de memória, em virtude do operador unário & aplicado em a e em b.
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5 &101
111 112 113 114 115 116 117 118 119 120
&105
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
*a 109 int
*b 111 int
temp 113 int
Figura 465 – O programa cria normalmente a variável temp da função troca
410
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5 &101
111 112 113 114 115 116 117 118 119 120
&105 7
Variáveis:main
a 101 int
b 105 int
Variáveis:troca
*a 109 int
*b 111 int
temp 113 int
Figura 466 – Chamada da função
Na chamada da função é que começam as diferenças.
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
411
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Memória RAM
101 102 103 104 105 106 107 108 109 110
7 5 &101
111 112 113 114 115 116 117 118 119 120
&105 7
Variáveis:main
A 101 int
B 105 int
Variáveis:troca
*a 109 int
*b 111 int
temp 113 int
Figura 467 – Armazenamento do valor 7 em temp 
A variável temp recebe o conteúdo apontado pela variável a da função troca. Como a variável a 
aponta para o endereço 101 e é do tipo inteiro, o valor 7 é armazenado em temp. 
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
5 5 &101
111 112 113 114 115 116 117 118 119 120
&105 7
Variáveis:main
A 101 int
B 105 int
Variáveis:troca
a 109 int
b 111 int
temp 113 int
Figura 468 – O endereço &101 recebe o valor do endereço &105
O endereço apontado pela variável a da função troca recebe o conteúdo apontado pela variável b da 
função troca, ou seja, no endereço &101, receberá o valor que está no endereço&105.
412
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
5 5 &101
111 112 113 114 115 116 117 118 119 120
&105 7
Variáveis:main
A 101 int
B 105 int
Variáveis:troca
a 109 int
b 111 int
temp 113 int
Figura 469 – O endereço &105 recebe o valor 7 do temp
O endereço apontado pela variável b da função troca recebe o conteúdo da variável temp dessa 
função, ou seja, no endereço &105, receberá o valor 7 do temp. O programa retorna para o ponto em 
que foi chamado.
#include<stdio.h>
void troca(int *a, int *b){
 int temp;
 temp=*a;
 *a=*b;
 *b=temp;
}
void main(){
 int a=7,b=5;
 troca(&a,&b);
 printf(“\na=%d\nb=%d\n”,a,b);
}
413
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Memória RAM
101 102 103 104 105 106 107 108 109 110
5 5 &101
111 112 113 114 115 116 117 118 119 120
&105 7
Variáveis:main
A 101 int
B 105 int
Variáveis:troca
a 109 int
b 111 int
temp 113 int
Tela:
a=5
b=7
Figura 470 – As variáveis a e b da função principal estão com os valores trocados
Nesse exemplo, vimos que a passagem de valor por referência permite que variáveis criadas em uma 
função possam ser alteradas fora dela. Essa técnica se torna importante, principalmente, pelo fato de a 
linguagem C não passar vetores e matrizes como parâmetros de uma função.
6.4 Passagem de vetores para funções
Como dito, a linguagem C não passa vetores como parâmetros de função; assim, a maneira que temos 
para fazê-lo é passando o endereço da primeira posição do vetor. Dessa forma, para receber um vetor, devemos 
colocar uma declaração do mesmo tipo do vetor com a indicação de que é um ponteiro (usando o *).
Exemplo de aplicação
Dado o programa a seguir:
include <stdio.h>
void incrvetor (int n, int *v) {
 int i;
 for (i = 0; i < n; i++) 
 v[i]++;
}
void main ( ) {
 int a[ ] = {1, 3, 5}; 
 incrvetor(3, a);
 printf(“%d %d %d \n”, a[0], a[1], a[2]); 
}
414
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Na função main() é criado o vetor inteiro a[], que será passado como parâmetro para a função 
incvetor(). Assim, a função recebe o endereço do vetor a pela declaração int * v. Nesse caso, o vetor é 
chamado de a na função main() e, dentro da função incvetor(), é tratado como v. Como ambos têm o 
mesmo endereço, ambos se referem ao mesmo espaço de memória.
O resultado desse programa é:
Figura 471 – Saída do programa com passagem de vetor na função
O programa passa como parâmetros um número e um vetor; este tem como elementos os valores {1, 
3, 5}. A função recebe o endereço do vetor, refere-se a ele como v e acrescenta 1 a cada elemento; assim, 
o vetor é alterado para {2, 4, 6}.
 lembrete
As bibliotecas de funções são anexadas ao programa principal pela 
diretiva de pré-compilação #include. Vimos até agora as bibliotecas stdio.h 
e string.h.
6.5 Funções da biblioteca-padrão
Muitas vezes, o uso de vetores e matrizes fica limitado pela necessidade de sabermos antecipadamente 
a quantidade de elementos que serão necessários. O interessante seria termos condições de criar e 
destruir elementos sem a limitação (apenas da máquina, e não da lógica), conforme forem surgindo as 
necessidades de uso.
A biblioteca stdlib.h possui algumas funções que nos permitem criar e trabalhar dinamicamente, 
ou seja, durante a execução de um certo trecho do programa. Para isso, precisamos entender algumas 
funções e utilizar os conhecimentos do uso da memória que vimos até agora.
A melhor forma de usarmos todas as funções necessárias a partir deste momento do curso é 
mostrando que, fazendo manualmente, o trecho
 int *v;
 v = (int*) malloc(10*sizeof(int));
415
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
é equivalente a simplesmente declararmos:
 int v[10];
Para estudarmos com detalhes o trecho, vamos analisar minuciosamente como é escrita a segunda linha.
Começamos com a memória fictícia vazia; temos o endereço começando do 101 e, logo abaixo, o seu byte.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
Variáveis:
nome endereço tipo
Figura 472 – Memória fictícia vazia, começando do 101
Para termos uma referência:
int *v;
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
Variáveis:
*v 101 int
Figura 473 – O ponteiro v é alocado na posição 101
416
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
A primeira função é o malloc(int), memory allocation ou alocação de memória. A função 
malloc reserva a quantidade de bytes que é passada como parâmetro e retorna o endereço em que 
esse espaço de memória foi reservado. Assim, se quisermos reservar o espaço de dez elementos 
inteiros para um vetor, imaginando que cada elemento de inteiro use 2 bytes (esse é um número 
puramente fictício, pois cada compilador pode ter um tamanho diferente), poderemos reservar 
20 bytes de memória.
malloc(20)
Considerando que 20 é 10* 2, dez elementos de 2 bytes. A função devolverá o valor &103, que é o 
endereço em que o espaço foi alocado.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
Variáveis:
*v 101 int
Figura 474 
Neste momento, se fizermos
 v=malloc(20);
o programa irá acusar erro, pois existe um conflito de informações: a variável v é um ponteiro 
apontando para inteiro, e o espaço de memória não corresponde à informação de um valor 
inteiro.
Voltando ao número 20, não sabemos ao certo se a quantidade de bytes que uma variável do tipo 
inteiro ocupa é realmente 2 bytes. Para descobrir quantos bytes um tipo ocupa, a biblioteca nos fornece 
a função sizeof(tipo), tamanho de. Essa função retorna um número inteiro que um tipo ocupa, seja ele 
preexistente, seja criado por nós com otypedef.
417
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Assim, por exemplo, se fizermos
sizeof( int )
ele devolverá a quantidade de bytes utilizados por uma variável do tipo int. Então, se quisermos um 
vetor de 10 elementos, inteiros, bastará fazer:
10 x sizeof(int)
Assim, se colocarmos
malloc(10*sizeof(int))
teremos o tamanho correto para alocarmos 10 números inteiros.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
Variáveis:
*v 101 int
Figura 475 – Alocados dez números inteiros
Agora o espaço alocado está correto, mas a expressão
v= malloc(10*sizeof(int))
continua acusando erro, pois v é um ponteiro inteiro, e esse espaço alocado não corresponde ao de 
inteiro.
Vimos na Unidade II um item chamado conversão de tipos, o chamado cast. Agora, isso será 
útil, pois transforma qualquer coisa em um tipo de variável. Nesse caso, servirá para formatar ou 
adequar o espaço alocado. Como o tipo de v é um ponteiro inteiro, aplicaremos a conversão do 
tipo int *.
418
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Assim, a expressão fica:
v=(int *)malloc(10*sizeof(int));
Com isso, a informação devolvida pelo malloc fica completa: um endereço e o tipo correspondente.
Ao aplicarmos o cast, a memória ficará assim:
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
&103
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
Variáveis:
*v 101 int
Figura 476 – Cast aplicado
Para liberar um espaço de memória alocado dinamicamente, utiliza-se a função free da biblioteca 
stilib.h. Essa função recebe como parâmetro o ponteiro da memória a ser liberada, e o espaço alocado é 
liberado para outros usos futuros. Assim, para liberar o vetor v, fazemos:
 free(v);
 observação
Os ponteiros também têm uma aritmética própria. Ao fazermos uma 
soma de um número inteiro a um ponteiro, este apontará para o endereço 
com o avanço de múltiplos correspondente ao tamanho do tipo definido 
para ele.
419
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Assim, no exemplo anterior, podemos ter as seguintes equivalências:
Tabela 12 – Relação entre o ponteiro e o índice de um vetor
Expressão Fazer a expressão Equivale a fazer a expressão
int *x = v+0 printf(“%d”,*x) printf(“%d”,v[0])
int *x = v+1 printf(“%d”,*x) printf(“%d”,v[1])
int *x = v+2 printf(“%d”,*x) printf(“%d”,v[2])
int *x = v+3 printf(“%d”,*x) printf(“%d”,v[3])
int *x = v+4 printf(“%d”,*x) printf(“%d”,v[4])
6.6 recursividade
Vimos que os vetores são limitados porque, desde o começo, precisamos saber a sua dimensão, e 
tivemos como solução o uso da alocação dinâmica da memória, para casos em que, a cada execução 
do programa, as suas dimensões podem mudar. Agora existem casos em que não só a memória, mas 
também o próprio programa tem de se adaptar a uma situação diferente a cada momento. Não é prático 
alterar o programa antes de cada execução. Para solucionar alguns desses problemas, podemos utilizar a 
recursividade. Existem algumas situações que só podem ser contornadas por meio dela.
A recursividade é a possibilidade de uma função se chamar, ou, então, voltar a ser chamada após 
a execução de funções que ela mesma chamou. Isso quer dizer que, a cada chamada, o programa abre 
um novo espaço na memória para a sua execução. A cada chamada recursiva, é guardada uma cópia 
dos parâmetros, de modo que não percamos os valores dos parâmetros das chamadas anteriores. Em 
princípio, enquanto houver memória para a recursividade, a função poderá ser reutilizada.
As funções recursivas têm duas características importantes:
•	 ponto	de	parada:	geralmente,	um	limite	superior	ou	inferior	da	regra	geral;
•	 regra	geral:	reduz	a	resolução	do	problema	por	meio	da	invocação	recursiva	de	casos	menores,	
resolvidos mediante a resolução de casos ainda menores, e assim sucessivamente, até atingir o 
ponto de parada, que finaliza o método.
As funções que não são recursivas são chamadas de iterativas.
Exemplo de aplicação
Multiplicação de inteiro:
#include <stdio.h>
int mult(int x, int y){
 if (y == 1){
420
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
mult(2,3)
2+mult(2,2)
2+mult(2,1)
2+ 2
2+ 4
6
Figura 477 – Modelo de chamada e retorno recursivos
A função se chama sucessivamente e, a cada chamada, o valor do parâmetro y decresce, até chegar 
ao ponto de parada, (y==1), e passa a ter retornos sucessivos, até a primeira chamada.
Fazendo o teste de mesa, temos:
#include <stdio.h>
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
421
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
#include <stdio.h>
int mult(int x, int y){
}
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
Variáveis:main
mult(2,3)
Figura 478 – A função main chama a função mult( ), passando como parâmetros 2 e 3
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3
111 112 113 114 115 116 117 118 119 120
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
Figura 479 – A função mult( ) é executada, criando na memória as 
variáveis x e y e recebendo os valores passados pela função main( )
422
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3
111 112 113 114 115 116 117 118 119 120
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
Figura 480 – Como y (na posição 103) não é 1, o programa passa para o else
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
423
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2
111 112 113 114 115 116 117 118 119 120
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
mult(2,2)
Figura 481 – Executando a função mult( )
No else, a primeira operação a ser executada é a chamada função mult( ), agora com os parâmetros 
x=2 e y-1, ou seja, 2.
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
424
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2
111 112 113 114 115 116 117 118 119 120
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
mult(2,2)
Variáveis:mult
x 105 int
y 107 int
Figura 482 – Uma nova função mult( ) é aberta, e são criadas as variáveis x e y na memória
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
425
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2
111 112 113 114 115 116 117 118 119 120
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
mult(2,2)
Variáveis:mult
x 105 int
y 107 int
Figura 483 – Como y vale 2, o else é executado
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
426
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2
111 112 113 114 115 116 117 118 119 120
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
mult(2,2)
Variáveis:mult
x 105 int
y 107 int
mult(2,1)
Figura 484 – Uma nova instância (rotina) do mult é chamada, agora com os parâmetros 2 e 1
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
427
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2 2
111 112 113 114 115 116 117 118 119 120
1
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
mult(2,2)
Variáveis:mult
x 105 int
y 107 int
mult(2,1)
Variáveis:mult
x 109 int
y 111 int
Figura 485 – Na nova instância, novos x e y são criados na memória
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
 return(x);
428
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
 }else{
 return(x + mult(x, y-1));
 }
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2 2
111 112 113 114 115 116 117 118 119 120
1
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
mult(2,2)
Variáveis:mult
x 105 int
y 107 int
2
Variáveis:mult
x 109 int
y 111 int
Figura 486 – Execução do return
Como o y chegou ao 1, dizemos que chegou ao ponto de parada, em que a função não é mais 
chamada recursivamente. Nesse ponto, o programa executa o return(x), ou seja, retorna o conteúdo de 
x, que é 2, para a função que o chamou.
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
int mult(int x, int y){
 if (y == 1){
429
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2 2
111 112 113 114 115 116 117 118 119 120
1
Variáveis:main
mult(2,3)
Variáveis:mult
x 101 int
y 103 int
4
Variáveis:mult
x 105 int
y 107 int
2
Figura 487 – Retorno do valor 4 
Ao receber de volta o resultado da função mult que foi chamado, a rotina soma com x e retorna, 
agora, 4.
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
int mult(int x, int y){
 if (y == 1){
 return(x);
 }else{
 return(x + mult(x, y-1));
 }
}
430
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2 2
111 112 113 114 115 116 117 118 119 120
1
Variáveis:main
6
Variáveis:mult
x 101 Int
y 103 Int
4
Figura 488 – Retorno do valor 6
Recebendo o valor de mult, a rotina retorna x + 4, que vale 6.
#include <stdio.h>
void main ( ) {
 printf(“\n %d x %d = % d”, 2,3,mult(2,3));
}
Memória RAM
101 102 103 104 105 106 107 108 109 110
2 3 2 2 2
111 112 113 114 115 116 117 118 119 120
1
Variáveis:main
6
Figura 489 – Recursivamente, há o retorno do programa ao ponto em que foi chamado
No exemplo da multiplicação, o ponto de parada é >.
 (y == 1)
Regra geral:
x + mult(x, y-1)
431
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
 observação
Um dos exemplos clássicos de recursividade é a implementação do jogo 
Torre de Hanói em uma simples rotina:
void moveHanoi(int ndiscos, char origem, char destino, char auxiliar){
 if(ndiscos > 0) {
 moveHanoi(ndiscos -1,origem, auxiliar, destino);
 printf(“mover de %c para %c\n”,origem, auxiliar);
 moveHanoi(ndiscos -1, auxiliar, destino,origem);
 } 
}
Uma vez determinada a quantidade de discos, e os pinos (‘a’, ‘b’, ‘c’) 
origem, destino e auxiliar, recursivamente, os pinos são alternados para 
serem movidos e esvaziados.
 lembreteO limite físico das funções recursivas é o amanho da memória RAM, 
pois, a cada nova chamada, a pilha das funções consome a memória livre.
 observação
A recursividade é tão importante que alguns problemas computacionais 
somente podem ser resolvidos por meio dela. Programas como saída de 
labirinto, simulação de jogos de xadrez e simulação meteolorógica são 
exemplos que usam a recursividade.
 Saiba mais
Um programa para percorrer um labirinto só pode ser feito por meio 
da recursividade. Cada labirinto tem um caminho diferente do outro, e, 
para adaptar-se a todos eles, o programa deve, repetidamente, percorrer 
caminhos não percorridos e voltar até o ponto em que algum caminho 
ainda não tenha sido percorrido, em caso de não achar saída. O uso da 
recursividade torna-se o ideal para esse tipo de situação.
432
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
A implementação está disponível no documento de autoria do professor 
Fernando Vanini:
VANINI, F. Funções recursivas. Unicamp, 7 ago. 2008. p. 14. Apresentação 
de aula. Disponível em: <http://www.ic.unicamp.br/~vanini/mc202/
apresentacoes/aula3.pdf>. Acesso em: 28 maio 2014.
 resumo
Nesta unidade, passamos a utilizar a linguagem como protótipo. A 
primeira coisa que fizemos foi ver como funcionam o gerenciamento e a 
alocação da memória.
Toda variável criada possui três propriedades: o seu nome, o seu tipo 
e o endereço da memória em que está alocada. Utilizando as informações 
tipo e endereço, também podemos trabalhar no programa como se fosse 
uma variável. Isso é possível graças aos ponteiros, variáveis que têm a 
informação do endereço e do tipo que contém esse local.
Graças a essa dupla atribuição, rotinas diferentes podem trabalhar com 
o mesmo dado, simultaneamente, assim como passar strings e vetores 
entre funções.
Funções da biblioteca stdlib.h permitem criar novas variáveis 
dinamicamente, usando as funções malloc() e sizeof(), bem como fazendo 
um cast no tipo.
Em seguida, estudamos a recursividade, na qual a função, em algum 
momento, volta a se chamar. Com as sucessivas chamadas, em algum 
instante, é preciso quebrar a cadeia de chamadas e retornar uma a uma 
as chamadas efetuadas, de trás para frente. Esse evento, que provoca a 
interrupção, fazendo a função parar de chamar-se, é denominado ponto de 
parada, e as mudanças efetuadas nos dados a cada chamada denominam-se 
regra geral. Vale lembrar que existem situações que somente é possível 
resolver por meio da recursividade.
433
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
 exercícios
Questão 1. Considere as seguintes estruturas:
typedef struct no{
 float info;
 struct no* proximo;
} No;
typedef struct pilha{
 No* primeiro;
}
Que tipo(s) de valor armazenará(ão) a variável “primeiro”?
A) Estrutura nó.
B) Endereço de memória.
C) Estrutura pilha.
D) Número com ponto flutuante e estrutura.
E) Número com ponto flutuante e um endereço de memória.
Resposta correta: alternativa B.
Análse das alternativas
A) Alternativa incorreta.
Justificativa: entre as estruturas, aquela que armazena a estrutura de nó é no.
B) Alternativa correta.
Justificativa: a variável primeiro é um ponteiro, e todo ponteiro armazena um endereço de memória.
C) Alternativa incorreta.
Justificativa: pilha é que armazena estrutura de pilha, e não a variável “primeiro”.
434
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Unidade VI
D) Alternativa incorreta.
Justificativa: não existe nenhuma estrutura que armazene ponto flutuamte e estrutura.
E) Alternativa incorreta.
Justificativa: a estrutura nó armazena um ponto flutuante e um endereço de memória.
Questão 2. Considere o programa a seguir:
#include <stdio.h>
int fatorial(int num){
 if(num < 0){ 
 return(-1);
 }
 if((num == 0) || (num == 1)){
 return(1);
 }else{
 return( num * fatorial( num - 1 ) );
 }
}
void main(){
 printf(“A combinãcao de 3 2 a eh %d\n”, fatorial(3)/ (fatorial(2)* fato-
rial(3-2))) ;
}
Considerando esse programa, assinale a alternativa correta:
A) A função fatorial é recursiva, e sua regra geral é if((num == 0) || (num == 1)).
B) A função fatorial é recursiva, e seu ponto de retorno é if((num == 0) || (num == 1)).
C) A função fatorial não é recursiva, pois a resolução é iterativa.
D) Uma função que é iterativa não pode ser recursiva.
E) A função fatorial é recursiva, e seu ponto de retorno é (num * fatorial( num - 1 ).
Resposta correta: alternativa B.
Análise das afirmativas
Justificativa geral: considerando que a função fatorial é recursiva pois chama a si, como as funções 
recursivas, tem duas características.
435
Re
vi
sã
o:
 Ju
lia
na
 -
 D
ia
gr
am
aç
ão
: J
ef
er
so
s /
 M
ár
ci
o 
- 
02
/0
6/
20
14
Linguagem e Técnicas de Programação
O ponto de retorno é quando a recursividade é interrompida, passando a retornar uma a uma 
as funções chamadas. Nessa função, a única maneira de não se chamar acontece quando ocorre a 
condicional.
 if((num == 0) || (num == 1)){
 return(1);
A cada chamada recursiva, o retorno é modificado, conforme:
 ( num * fatorial( num - 1 )
Essa é a regra geral.

Continue navegando