Computadores Digitais 2
Prof. Rodrigo de Souza Couto
Linguagens de Programação – DEL-Poli/UFRJ
Prof. Miguel Campista
Aula de Hoje
•
•
•
•
•
•
•
•
•
•
Funções padrão do C
Definição de funções
Pilha de execução
Ponteiros de variáveis
Variáveis globais
Variáveis estáticas
Escopo de funções
Recursividade
Pré-processador e macros
Módulos e compilação em separado
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
ATENÇÃO
• Esta apresentação foi baseada nos seguinte trabalhos:
– Notas de aula do Prof. Miguel Campista da UFRJ
• http://www.gta.ufrj.br/~miguel/lingprog.html
– Notas de aula do Prof. Marco Casanova da PUC-Rio
• http://www.inf.puc-rio.br/~inf1620/material.html
– Waldemar Celes, Renato Cerqueira, José Lucas Rangel,
“Introdução a Estruturas de Dados”, Editora Campus,
2004
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Parte 1
Programação (linguagem C)
Funções
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Funções
• Facilitam o projeto, a implementação, a operação e a
manutenção de programas grandes
– Técnica dividir para conquistar
• Constrói um grande programa por meio de peças simples e
pequenas
• Ex: Programa de uma calculadora simples
– Função de Soma e Subtração
– Função de Divisão e Multiplicação
– Função de entrada de operandos
– Função de exibição de resultados
– Funções da C Standard Library
• Ex: printf e scanf
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Funções
• Uma função é chamada por uma chamada de função
– A função chamada retorna um resultado ou
simplesmente retorna o controle ao chamador
– As chamadas de função formam relacionamentos
hierárquicos
Função Principal
Função 1
Função 3
Função 2
Função 4
Computadores Digitais II– DETEL-FEN/UERJ
Função 5
Prof. Rodrigo de Souza Couto
C Standard Library
• É uma coleção de funções para a execução de
operações comuns como
–
–
–
–
–
Cálculos matemáticos
Manipulação de strings
Manipulação de caracteres
Entrada/Saída
Verificação de erros
• É fornecida como parte do ambiente de programação
do C
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de funções da
C Standard Library
• Funções da biblioteca de matemática
– Diversas funções matemáticas não especificadas
nativamente em C
• Seno, Cosseno, Raiz Quadrada, etc.
– Para utilizá-la é necessário incluir seu cabeçalho
disponível no math.h
• #include <math.h>
• Similar ao caso de printf e scanf incluídas com stdio.h
• Veremos mais à frente detalhes sobre cabeçalhos!
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de uso da biblioteca
matemática
• Impressão de √900 e 27
#include <stdio.h>
#include <math.h>
int main(void) {
printf (“%.2f”,sqrt(900));
printf (“%.2f”,pow(2,7));
return 0;
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Algumas funções da
biblioteca matemática
Função
Descrição
ceil(x)
Arredonda x para o menor inteiro maior ou igual a x
cos(x)
Co-seno de x (x em radianos)
exp(x)
Função exponencial (ex)
fabs(x)
Valor absoluto de x
floor(x)
Arredonda x para o maior inteiro menor ou igual a x
fmod(x, y)
Resto de x/y como um número de ponto flutuante
log(x)
Logaritmo natural (base e) de x
log10(x)
Logaritmo na base 10 de x
pow(x, y)
x elevado a y
sin(x)
Seno de x (x em radianos)
sqrt(x)
Raiz quadrada de x
tan(x)
Tangente de x (x em radianos)
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Algumas funções da
biblioteca matemática
Função
Descrição
ceil(x)
Arredonda x para o menor inteiro maior ou igual a x
cos(x)
Co-seno de x (x em radianos)
exp(x)
Função exponencial (ex)
fabs(x)
Valor absoluto de x
floor(x) Vejam Arredonda
x para ocomo
maior
inteiro
menoreou
igual a x em:
mais formalismos,
tipo
retornado
argumentos,
fmod(x, y)
Resto de x/y como um número de ponto flutuante
log(x) http://www.tutorialspoint.com/c_standard_library/math_h.htm
Logaritmo natural (base e) de x
log10(x)
Logaritmo na base 10 de x
pow(x, y)
x elevado a y
sin(x)
Seno de x (x em radianos)
sqrt(x)
Raiz quadrada de x
tan(x)
Tangente de x (x em radianos)
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Definição de Funções
• Tipo Retornado
– Tipo do valor retornado ao fim da execução da função
• Nome da função
– Nome utilizado para chamar a função no programa
• Lista de parâmetros
– Parâmetros recebidos pela função
• Tipo e nome dos parâmetros
tipoRetornado nomeFuncao (listaParametros){
corpo da função
...
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
int f = 1;
for (i = 1; i <= n; i++)
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
Protótipo da função. Deve
ser incluído antes de a
função ser chamada.
É comum incluir protótipos
em um arquivo “.h”, como
será visto mais tarde
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
int f = 1;
for (i = 1; i <= n; i++)
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
void é uma palavra
reservada que indica
ausência de parâmetros ou
de valor de retorno
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
int f = 1;
for (i = 1; i <= n; i++)
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
Chamada da Função
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
int f = 1;
for (i = 1; i <= n; i++)
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
main retorna um inteiro. Por
convenção, retorna 0 caso a
execução seja bem
sucedida. Esse inteiro pode
ser utilizado pelo Sistema
Operacional
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
int f = 1;
for (i = 1; i <= n; i++)
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
fatorial não retorna
int f = 1;
valores
for (i = 1; i <= n; i++)
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
fatorial recebe parâmetro
int f = 1;
do tipo int
for (i = 1; i <= n; i++)
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
Variável n na função
int f = 1;
fatorial é uma variável
for (i = 1; i <= n; i++)
diferente da função main
f *= i;
printf (“Fatorial = %d\n”, f);
}
Exemplo: Cálculo de Fatorial
#include <stdio.h>
void fatorial (int n);
/*Função principal */
int main(void) {
int n;
scanf (“%d”,&n);
fatorial(n);
return 0;
}
/*Função para imprimir o valor do fatorial */
void fatorial (int n) {
int i;
Para evitar confusões, é
int f = 1;
bom sempre evitar repetir
for (i = 1; i <= n; i++)
nomes de variáveis
f *= i;
printf (“Fatorial = %d\n”, f);
}
Cálculo de Fatorial:
Outra Forma de implementar
#include <stdio.h>
int fatorial (int n);
Função fatorial retorna o
/*Função principal */
valor e função main o
int main(void) {
exibe
int n, r;
scanf (“%d”,&n);
r = fatorial(n);
printf (“Fatorial = %d\n”, r);
return 0;
}
/*Função para imprimir o valor do fatorial */
int fatorial (int n) {
int i;
int f = 1;
for (i = 1; i <= n; i++)
f *= i;
return f;
}
Cálculo de Fatorial:
Outra Forma de implementar
#include <stdio.h>
int fatorial (int n);
/*Função principal */
int main(void) {
int n, r;
scanf (“%d”,&n);
r = fatorial(n);
printf (“Fatorial = %d\n”, r);
return 0;
}
/*Função para imprimir o valor do fatorial */
int fatorial (int n) {
int i;
Melhor prática de
int f = 1;
programação:
for (i = 1; i <= n; i++)
Apenas função main
f *= i;
imprime resultados
return f;
}
Exercício
• A partir da função fatorial, escreva uma função
que calcule o número de combinações de n elementos
tomados k a k, na qual a ordem é relevante
– Arranjo
– Fórmula:
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Resposta do Exercício
int arranjo(int n, int k) {
int a;
a = fatorial(n)/fatorial(n-k);
return a;
}
Ou
int arranjo(int n, int k) {
return fatorial(n)/fatorial(n-k);
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Boas Práticas com Funções
• As funções devem ser limitadas à realização de uma
tarefa bem definida
– Programas simples são mais fáceis de escrever, testar,
depurar e manter
• Dica: O nome da função deve expressar essa tarefa
efetivamente
– Caso isso não seja possível, é provável que a função
esteja tentando realizar um número muito grande de
tarefas
• Nesse caso, é melhor dividir essa função em funções
menores
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Comunicação entre Funções
• Funções são independentes entre si
• Transferência de dados entre funções
– Através dos parâmetros e do valor de retorno da
função chamada
– Passagem de parâmetros é feita por valor
Comunicação entre Funções
• Funções são independentes entre si
• Transferência de dados entre funções
– Através dos parâmetros e do valor de retorno da
função chamada
– Passagem de parâmetros é feita por valor
...
int main(void) {
int n, r;
scanf (“%d”,&n);
r = dobro(n);
printf (“Dobro de %d = %d\n”,n, r);
return 0;
}
Função dobro não altera o
int dobro (int b) {
valor de n, pois não recebeu
b = b*2;
de fato a variável, e sim seu
return b;
valor
}
Comunicação entre Funções
• Variáveis locais a uma função
– Definidas dentro do corpo de uma função
• Incluindo os parâmetros
– Não existem fora da função
– São criadas cada vez que a função é executada
– Deixam de existir quando a execução da função
terminar
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exercício
#include <stdio.h>
int dobrar (int n);
int main(void) {
int r, i;
i = 1;
while (i < 10) {
r = dobrar(i)
printf (“%d ”,r);
}
return 0;
}
int dobrar (int i) {
i = i * 2;
return i;
}
Computadores Digitais II– DETEL-FEN/UERJ
Qual a saída do programa?
Prof. Rodrigo de Souza Couto
Exercício
#include <stdio.h>
int dobrar (int n);
int main(void) {
int r, i;
i = 1;
while (i < 10) {
r = dobrar(i)
printf (“%d ”,r);
}
return 0;
}
int dobrar (int i) {
i = i * 2;
return i;
}
Computadores Digitais II– DETEL-FEN/UERJ
2 2 2 2 2 2 2 2 2….
E nunca termina, pois valor
de i não se altera!!!
Prof. Rodrigo de Souza Couto
Comunicação entre Funções
• Como é implementada a comunicação entre funções?
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Comunicação entre Funções
• Como é implementada a comunicação entre funções?
– Pilha de Execução!
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Pilha de Execução
• Cada variável local de uma
função é colocada na pilha de
execução
• Ao chamar uma função, os
parâmetros são copiados para a
pilha
– Parâmetros são tratados como
variáveis locais da função
• Variáveis da pilha referentes à
função são liberadas após seu
término
Computadores Digitais II– DETEL-FEN/UERJ
c
‘x’
b
43.5
7
a
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
f *= n;
n--;
}
return f;
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
Atenção: A pilha está
representada aqui de forma
bem simplificada para fins
didáticos!!
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
f *= n;
n--;
}
return f;
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
Início do programa: pilha
vazia
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
f *= n;
n--;
}
return f;
main >
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
Declaração de variáveis: n, r
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
f *= n;
n--;
r
xxxxxx
}
n
return f;
5
main >
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
Chamada de função: cópia
do parâmetro
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
f *= n;
n
5
n--;
fatorial >
r
xxxxxx
}
n
return f;
5
main >
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
Declaração da variável local:
f
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
1
f
f *= n;
n
5
n--;
fatorial >
r
xxxxxx
}
n
return f;
5
main >
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
Final do laço while
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
f
120
f *= n;
n
0
n--;
fatorial >
r
xxxxxx
}
n
return f;
5
main >
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo de Pilha
#include <stdio.h>
int fatorial (int n);
Retorno da função:
desempilha
int main(void) {
int n = 5;
int r;
r = fatorial(n);
printf (“Fatorial de %d = %d\n”, n , r);
return 0;
}
int fatorial (int n) {
int f = 1;
while ( n != 0 ) {
f *= n;
n--;
120
r
}
n
return f;
5
main >
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Comunicação entre Funções
• Até agora, passamos valores para as funções.
• E se desejássemos que a função alterasse o valor da
própria variável?
– “Retorno” de mais de uma variável
• Uma função pode retornar apenas um valor
• Em alguns casos é desejável o “retorno” de mais valores
– Ex: Função que calcula a soma E o produto de 2
valores
– Variáveis grandes
• P.ex. Vetores
• Realizar sua cópia para a pilha é ineficiente
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Ponteiros de Variáveis
• Variável do tipo ponteiro
– Permite o armazenamento e a manipulação de endereços
de memória
– Para cada tipo existente (int, float, etc.), existe um tipo
de ponteiro
/* Declaracao
int a;
/* Declaracao
int *p;
/* Declaracao
float f;
/* Declaracao
float *r;
de uma variável int */
de um ponteiro para int */
de uma variável float */
de um ponteiro para float */
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Ponteiros de Variáveis
• Operadores
– & (“endereço de”)
• Aplicado a variáveis, resulta no endereço da posição de
memória reservada para a variável
– * (“conteúdo de”)
• Aplicado a ponteiros, acessa o conteúdo do endereço de
memória apontado pelo ponteiro
int a = 5;
int c;
int *p;
p = &a;
*p = 6;
c = *p;
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Ponteiros de Variáveis
• Operadores
– & (“endereço de”)
• Aplicado a variáveis, resulta no endereço da posição de
memória reservada para a variável
– * (“conteúdo de”)
• Aplicado a ponteiros, acessa o conteúdo do endereço de
memória apontado pelo ponteiro
int a = 5;
int c;
int *p;
p = &a;
*p = 6;
c = *p;
Computadores Digitais II– DETEL-FEN/UERJ
Endereços
c
Nomes
p
a
xxxxxxx
112
xxxxxxx
108
104
5
Prof. Rodrigo de Souza Couto
Ponteiros de Variáveis
• Operadores
– & (“endereço de”)
• Aplicado a variáveis, resulta no endereço da posição de
memória reservada para a variável
– * (“conteúdo de”)
• Aplicado a ponteiros, acessa o conteúdo do endereço de
memória apontado pelo ponteiro
int a = 5;
int c;
int *p;
p = &a;
*p = 6;
c = *p;
p aponta para a
Computadores Digitais II– DETEL-FEN/UERJ
c
p
a
xxxxxxx
112
104
108
104
5
Prof. Rodrigo de Souza Couto
Ponteiros de Variáveis
• Operadores
– & (“endereço de”)
• Aplicado a variáveis, resulta no endereço da posição de
memória reservada para a variável
– * (“conteúdo de”)
• Aplicado a ponteiros, acessa o conteúdo do endereço de
memória apontado pelo ponteiro
int a = 5;
int c;
int *p;
p = &a;
*p = 6;
c = *p;
conteúdo de p recebe o
valor 6. Acessar a é
equivalente a acessar *p.
Computadores Digitais II– DETEL-FEN/UERJ
c
p
a
xxxxxxx
112
104
108
104
6
Prof. Rodrigo de Souza Couto
Ponteiros de Variáveis
• Operadores
– & (“endereço de”)
• Aplicado a variáveis, resulta no endereço da posição de
memória reservada para a variável
– * (“conteúdo de”)
• Aplicado a ponteiros, acessa o conteúdo do endereço de
memória apontado pelo ponteiro
int a = 5;
int c;
int *p;
p = &a;
*p = 6;
c = *p;
c recebe o conteúdo de p
Computadores Digitais II– DETEL-FEN/UERJ
c
p
a
6
112
104
108
104
6
Prof. Rodrigo de Souza Couto
Ponteiros de Variáveis
• Operadores
– & (“endereço de”)
• Aplicado a variáveis, resulta no endereço da posição de
memória reservada para a variável
– * (“conteúdo de”)
• Aplicado a ponteiros, acessa o conteúdo do endereço de
memória apontado pelo ponteiro
int a = 5;
int c;
int *p;
p = &a;
*p = 6;
c = *p;
Representação gráfica
Computadores Digitais II– DETEL-FEN/UERJ
c
p
a
6
6
Prof. Rodrigo de Souza Couto
Exercício 1
• Qual é a saída do programa abaixo?
#include <stdio.h>
int main(void) {
int a = 5;
int *p;
p = &a;
*p = 2;
printf (“Saida %d
return 0;
}
Computadores Digitais II– DETEL-FEN/UERJ
”, a);
Prof. Rodrigo de Souza Couto
Exercício 1
• Qual é a saída do programa abaixo?
#include <stdio.h>
int main(void) {
int a = 5;
int *p;
p = &a;
*p = 2;
printf (“Saida %d
return 0;
}
”, a);
Saida 2
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exercício 2
• O que há de errado com o programa abaixo?
• Ele poderia funcionar?
#include <stdio.h>
int main(void) {
int a, b, *p;
a = 2;
*p = 3;
b = a + (*p);
printf (“Saida %d
return 0;
}
Computadores Digitais II– DETEL-FEN/UERJ
”, b);
Prof. Rodrigo de Souza Couto
Exercício 2
• O que há de errado com o programa abaixo?
• Ele poderia funcionar?
#include <stdio.h>
int main(void) {
int a, b, *p;
a = 2;
*p = 3;
b = a + (*p);
printf (“Saida %d ”, b);
return 0;
}
Endereço armazenado em p
não é conhecido (no início
possui valor lixo, que pode
ser qualquer posição de
memória)
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exercício 2
• O que há de errado com o programa abaixo?
• Ele poderia funcionar?
#include <stdio.h>
int main(void) {
int a, b, *p;
a = 2;
*p = 3;
b = a + (*p);
printf (“Saida %d ”, b);
return 0;
Programa pode funcionar,
}
mas seu comportamento é
inesperado. Por exemplo, o
endereço de memória
apontado por p pode estar
em uso.
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Passando ponteiros para
funções
• Permite que a função altere as variáveis
– Útil quando é necessário retornar mais de um valor
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Passando ponteiros para
funções
#include <stdio.h>
void somaprod (int a, int b, int *p, int *q);
int main(void) {
int s,z;
somaprod(3,5,&s,&z);
printf (“Soma = %d Produto = %d \n”, s,z);
return 0;
}
void somaprod (int a, int b, int *p, int *q){
*p = a + b;
*q = a * b;
}
124
120
116
112
main >
108
104
Passando ponteiros para
funções
#include <stdio.h>
void somaprod (int a, int b, int *p, int *q);
int main(void) {
int s,z;
somaprod(3,5,&s,&z);
printf (“Soma = %d Produto = %d \n”, s,z);
return 0;
}
void somaprod (int a, int b, int *p, int *q){
*p = a + b;
*q = a * b;
}
124
120
116
112
Declaração das variáveis s,z
sem inicialização
z
main >
s
xxxxxxx
xxxxxxx
108
104
Passando ponteiros para
funções
#include <stdio.h>
void somaprod (int a, int b, int *p, int *q);
int main(void) {
int s,z;
somaprod(3,5,&s,&z);
printf (“Soma = %d Produto = %d \n”, s,z);
return 0;
}
void somaprod (int a, int b, int *p, int *q){
*p = a + b;
*q = a * b;
}
somaprod >
Chamada da função: recebe
valores e endereços
main >
q
108
124
p
104
120
b
a
5
116
3
xxxxxxx
xxxxxxx
112
z
s
108
104
Passando ponteiros para
funções
#include <stdio.h>
void somaprod (int a, int b, int *p, int *q);
int main(void) {
int s,z;
somaprod(3,5,&s,&z);
printf (“Soma = %d Produto = %d \n”, s,z);
return 0;
}
void somaprod (int a, int b, int *p, int *q){
*p = a + b;
*q = a * b;
}
somaprod >
Conteúdo de s,z recebem soma
e produto, respectivamente
main >
q
108
124
p
104
120
b
a
5
116
3
15
8
112
z
s
108
104
Passando ponteiros para
funções
#include <stdio.h>
void somaprod (int a, int b, int *p, int *q);
int main(void) {
int s,z;
somaprod(3,5,&s,&z);
printf (“Soma = %d Produto = %d \n”, s,z);
return 0;
}
void somaprod (int a, int b, int *p, int *q){
*p = a + b;
*q = a * b;
}
124
120
116
112
Finalização da função: variáveis
locais desempilhadas
z
main >
s
15
8
108
104
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Declaração de variáveis a, b
120
116
112
b
7
a
main >
5
108
104
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Chamada da função
120
py
108
104
116
b
7
a
main >
5
108
104
px
troca >
112
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Declaração de temp
temp
xxxxxxx
120
108
104
116
b
7
a
main >
5
108
104
py
px
troca >
112
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
temp
void troca (int *px, int *py){
py
int temp;
px
temp = *px;
troca >
*px = *py;
b
*py = temp;
a
}
main >
temp recebe conteúdo de px
5
120
108
104
116
7
108
104
5
112
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Conteúdo de px recebe
conteúdo de py
temp
5
120
108
104
116
b
7
a
main >
7
108
104
py
px
troca >
112
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Conteúdo de py recebe temp
temp
5
120
108
104
116
b
5
a
main >
7
108
104
py
px
troca >
112
Exercício
• Descreva o passo a passo do preenchimento da pilha
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Função termina
120
116
112
b
5
a
main >
7
108
104
Variáveis Globais
• Variáveis declaradas fora do corpo das funções
• Visível a todas funções subsequentes à declaração
• Não são armazenadas na pilha de execução
– Não deixam de existir quando a função termina
– Existem durante toda a execução do programa
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Variáveis Globais
#include <stdio.h>
int s,z;
void somaprod (int a, int b);
int main(void) {
int x,y;
scanf(“%d %d”, &x, &y)
somaprod(x,y);
printf (“Soma = %d Produto = %d \n”, s,z);
return 0;
}
void somaprod (int a, int b){
s = a + b;
z = a * b;
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Variáveis Globais
• Úteis quando utilizadas por muitas funções do
programa
• Recomenda-se evitar o uso desnecessário dessas
variáveis!!!!
– Ocupam a memória durante toda a execução do
programa
– Tornam a função menos geral
• Dependência de variáveis definidas fora da função
– Dificulta o reuso da função
– Perda do controle do comportamento da variável
• Quando muitas funções a utilizam, pode ser difícil depurar
seu comportamento
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Pré-processador e macros
• Pré-processador
– Reconhece determinadas diretivas
– Altera o código antes de enviá-lo ao compilador
programa.c
Préprocessador C
Compilador C
programa.o
Ligador
(linker)
programa.exe
Figura adaptada do livro “Sistemas Operacionais Modernos”, Andrew S. Tanenbaum, Terceira Edição, 2010.
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Pré-processador e macros
• #include nomeDoArquivo
– Pré-processador substitui o include pelo corpo do
arquivo especificado
• O texto do arquivo passa a fazer parte do código fonte
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo: Protótipo de função
separado
• Relembrando o
exemplo da função
troca
– Protótipo
declarado na
própria função
Computadores Digitais II– DETEL-FEN/UERJ
#include <stdio.h>
void troca (int *px, int *py);
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a , b);
return 0;
}
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Prof. Rodrigo de Souza Couto
Exemplo: Protótipo de função
separado
Arquivo troca.h
void troca (int *px, int *py);
Arquivo troca.c
#include “troca.h”
void troca (int *px, int *py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Computadores Digitais II– DETEL-FEN/UERJ
Arquivo exemplo.c
#include <stdio.h>
#include “troca.h”
int main(void) {
int a = 5 , b = 7;
troca(&a,&b);
printf (“%d %d \n”, a ,
b);
return 0;
}
Prof. Rodrigo de Souza Couto
Exemplo: Protótipo de função
separado
exemplo.c
exemplo.o
troca.c
Préprocessador C
Ligador
(linker)
Compilador C
programa.exe
troca.o
troca.h
libc.a
Figura adaptada do livro “Sistemas Operacionais Modernos”, Andrew S. Tanenbaum, Terceira Edição, 2010.
Pré-processador e macros
• #include nomeDoArquivo
– Pré-processador substitui o include pelo corpo do
arquivo especificado
• O texto do arquivo passa a fazer parte do código fonte
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Exemplo no Dev C++
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Pré-processador e macros
• #include nomeDoArquivo
– Pré-processador substitui o include pelo corpo do arquivo
especificado
• O texto do arquivo passa a fazer parte do código fonte
– O nome do arquivo entre aspas (#include “arquivo.h”)
• Pré-processador procura o arquivo primeiro no diretório local
– Diretório de Trabalho
• Caso não encontre, procura nos diretórios especificados na
compilação
– Nome do arquivo entre sinais de menor e maior
(#include <arquivo.h>)
• C Standard Library
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Pré-processador e macros
• Macro
– Fragmento de código que recebe um nome
– Em qualquer lugar que esse nome é utilizado o préprocessador substituiu pelo código
– Utilização
• Definições de constantes
• Definições de parâmetros
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Pré-processador e macros
• Macro para definição de constantes
– No exemplo abaixo toda a ocorrência da macro PI será
substituída por 3.14159F
• Facilita a manutenção e acrescenta clareza no código
#define PI 3.14159F
float area(float r) {
float a = PI * r * r;
return a;
}
Computadores Digitais II– DETEL-FEN/UERJ
Prof. Rodrigo de Souza Couto
Módulos e Compilação em
Seprado
Funções podem ser módulos
separados definidos em .c
other.c
other.o
help.c
main.c
mac.h
Préprocessador C
Compilador C
help.o
Ligador
(linker)
programa.exe
main.o
a.out
defs.h
Figura adaptada do livro “Sistemas Operacionais Modernos”, Andrew S. Tanenbaum, Terceira Edição, 2010.
Módulos e Compilação em
Seprado
other.c
other.o
help.c
main.c
mac.h
Préprocessador C
Compilador C
help.o
Arquivos .h indicam o
protótipo e devem ser
documentados
Ligador
(linker)
programa.exe
main.o
a.out
defs.h
Figura adaptada do livro “Sistemas Operacionais Modernos”, Andrew S. Tanenbaum, Terceira Edição, 2010.