Você está na página 1de 49

Projeto de Algoritmos

Funções

Neste tópico abordaremos a construções de


funções e C, procurando entender o
conceito de escopo de variáveis, os
mecanismos de passagem de parâmetros e
estimulando a modularização de
programas.

Prof. Ciro Cirne Trindade


Por quê usar funções?

 Evitar a repetição de um conjunto de


instruções que ocorre várias vezes no
programa
 Modularizar o programa
 Reaproveitamento de código

2
Estruturas das Funções em
C
tipo nome-da-função([lista-de-parâmetros]) {
corpo da função
}

tipo: especifica o tipo do valor que a função
retorna

lista-de-parâmetros: uma lista separada por
vírgulas das variáveis que recebem os valores
dos argumentos passados quando a função é
chamada

corpo da função: comandos delimitados por
chaves { }

3
Exemplo

#include <stdio.h>

void linha(void); //protótipo da função linha()

int main() {
linha();
printf("\n\t\t\t\tUm programa em C\n");
linha();
return 0;
}
void linha() {
int i;
for (i = 1; i <= 80; i++)
printf("-");
}

4
Protótipos de funções

 O protótipo de uma função informa ao


compilador o tipo e o nome da função,
além do número, ordem e tipos de seus
argumentos
 O compilador usa protótipos de funções
para validar as chamadas de funções
 void é usada na lista de parâmetros do
protótipo para indicar uma lista de
parâmetros vazia
5
Chamando Funções


Do mesmo modo que chamamos uma
função da biblioteca C (printf(),
scanf(), etc.) chamamos nossas
próprias funções como linha()

Os parênteses que seguem o nome são
necessários para que o compilador
possa diferenciar a chamada a uma
função de seu endereço de memória

6
Chamando funções
Função F1
Fluxo de Função Comando
controle main
Comando Função F3
Comando Comando

Comando
Chamada de F3 Comando
Comando
Chamada de F1 Comando final
Comando
Comando final

Comando Função F2
Comando

Chamada de F2
Comando Comando

Comando final Comando final


7
Escopo de Variáveis


Variáveis que são declaradas dentro de uma
função e são conhecidas somente dentro do
seu próprio bloco

Um bloco começa quando o compilador
encontra uma chave de abertura ({) e
termina quando o compilador encontra uma
chave de fechamento (})

Variáveis locais existem apenas durante a
execução do bloco de instruções onde estão
declaradas

Os blocos aonde uma variável é conhecida,
chama-se escopo da variável
8
Passando Argumentos para
Funções

O mecanismo usado p/ transmitir
informações a uma função é chamado
argumento

O argumento também é chamado de parâmetro
formal da função

O argumento é uma nova variável que
armazena a informação passada p/ a função

Funciona exatamente como uma variável local

É criada quando a função inicia sua execução e
destruída quando a função termina

9
Passando Argumentos para
Funções

Argumentos - chamada por valor

Em C, todos os argumentos de funções
são passados “por valor”, exceto vetores

Isto significa que à função chamada é
dada uma cópia dos valores dos
argumentos, e ela cria outras variáveis
temporárias para armazenar estes valores

A função chamada não pode alterar o
valor de uma variável da função que
chama; ela só pode alterar sua cópia
temporária
10
Exemplo
#include <stdio.h>
void dobro(int);

int main() {
int n;
printf("Informe um número inteiro: ");
scanf("%d", &n);
dobro(n);
printf("Número informado %d\n", n);
return 0;
}

void dobro(int x) {
x = x * 2;
printf("Dobro: %d\n", x);
}

11
Funções que Devolvem um
Valor

O comando return

Causa uma saída imediata da função onde
ele está contido, ou seja, termina a função

Pode ser usado para devolver um valor

Todas as funções, exceto aquelas do tipo
void, devolvem um valor

Este valor é explicitamente especificado pelo
comando return

O comando return faz com que a chamada à
função que contém o return seja substituída
pelo valor que sucede este comando

12
Funções que Devolvem um
Valor

Desde que uma função não seja declarada
como void, ela pode ser usada como um
operando em qualquer expressão
 x = pow(y, 2);
 if (max(x, y) > 100) printf("Maior");
 for (ch = getchar(); isdigit(ch); ) ...;
 printf("Valor absoluto de %d = %d", x, abs(x));

Entretanto, uma função não pode receber
uma atribuição
 sqr(x) = 100; // instrução errada

13
Exemplo
#include <stdio.h>

int maior(int, int); //protótipo da função maior()

int main() {
int n1, n2;
printf("Digite dois números inteiros: ");
scanf("%d %d", &n1, &n2);
printf("O maior é: %d\n", maior(n1, n2));
return 0;
}

int maior(int a, int b) {


if (a > b)
return a;
return b;
}

14
Conceito de Ponteiro

 Ponteiros são variáveis especiais que


armazenam endereços de memória
 Uma variável comum faz referência
direta a um valor específico
 Um ponteiro contém o endereço de
uma variável que contém um valor
específico
 Ou seja, um ponteiro é uma referência
indireta ao valor da variável cujo
endereço ele armazena 15
Conceito de Ponteiro

cont cont faz uma referência


direta à célula de memória
7
cujo valor é 7

pcont faz uma pcont cont


referência indireta
a uma variável 7
cujo valor é 7

16
Declarando Variáveis do
Tipo Ponteiro

Sintaxe:
 tipo * variável;

Exemplos:
 int * pcont;
 float * px, * py;

Todo ponteiro tem um tipo específico
que indica o tipo da variável para o qual
ele aponta

Um ponteiro inteiro deve armazenar o
endereço de memórias de variáveis inteiras
17
Inicializando Ponteiros


Um ponteiro pode ser inicializado com:

0: é convertido para um ponteiro do tipo
apropriado

NULL: uma constante simbólica definida na
arquivo de cabeçalho <stdio.h>

Um endereço de memória

18
Operadores de Ponteiros


2 operadores unários são usados:
 &: obtém o endereço de memória de uma

variável
 *: obtém o conteúdo do endereço de
memória armazenado em um ponteiro

Exemplo:
int cont = 7;
int * pcont = &cont;
printf("%d\n", *pcont);
19
Exemplo

#include<stdio.h>
int main() {
int x = 10;// x é um inteiro
int * px; // px é um ponteiro p/ inteiro
px = &x; // px recebe o endereço de x
printf("Endereço de x: %p\n", &x);
printf("Valor de px: %p\n", px);
printf("Valor de x: %d\n", x);
printf("Valor do endereço armazenado em px: %d\n",
*px);
/* alterando dados */
*px = 30;
printf("Valor de x: %d\n", x);
printf("Valor de px: %p\n", px);
return 0;
}
20
Passagem de Parâmetros
por Referência

Por default, a passagem de parâmetros em C
é feita por valor (com exceção de vetores e
matrizes)

Uma cópia do valor do parâmetro é
transmitida para a função

A função chamada não pode alterar o valor
de uma variável da função que chama; ela só
pode alterar sua cópia temporária

A passagem de parâmetros por referência
permite à função chamada alterar os valores
das variáveis que foram passadas como
parâmetro em sua chamada 21
Passagem de Parâmetros
por Referência

Na chamada à função, são
transmitidos os endereços das
variáveis

Usa-se o operador &

Os parâmetros da função devem ser
ponteiros

22
Exemplo
#include <stdio.h>

void troca(int *, int *);

int main() {
int a = 10, b = 20;

printf("a = %d, b = %d\n", a, b);


troca(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}

void troca(int * pa, int * pb) {


int aux = *pa;
*pa = *pb;
*pb = aux;
} 23
Exercícios
1)Criar uma função em C que receba como
parâmetro o valor de um ângulo em radianos e
converta-o para graus. Obs.: O parâmetro
passado na chamada à função deve ser
alterado para graus. Dica: graus =
radianos*180/ π.
2)Criar uma função em C que receba um número
inteiro n > 0 e devolve o número de dígitos de
n e o primeiro dígito de n.

24
Vetores como Argumentos
de Funções

Chamamos a função com o nome do
vetor/matriz sem nenhum índice

Passamos o endereço do 1o elemento do
vetor/matriz para a função

Exemplo:
int main() {
int vet[10];
. . .
fun(vet);
. . .
}

25
Vetores como Argumentos
de Funções

Se a função recebe um vetor, o parâmetro
formal pode ser um ponteiro, um vetor
dimensionado, ou um vetor sem dimensão
void fun(int *a) void fun(int a[10]) void fun(int a[])
{ { {
. . . . . . . . .
} } }
 Esses 3 métodos dizem ao compilador que um
ponteiro para um inteiro está sendo recebido
 Passagem de parâmetros por referência

26
Matrizes como Argumentos
de Funções

Se a função recebe uma matriz bidimensional
como argumento, o número de elementos da
segunda dimensão (colunas) deve ser incluído
no cabeçalho da função

Exemplo: suponha a uma matriz 4 x 6
void fun(int a[4][6]) void fun(int a[][6]) void fun(int (*a)[6])
{ { {
... ... ...
} } }

27
Matrizes como Argumentos
de Funções

A partir do C99 é possível definir a dimensão
de uma matriz que é o parâmetro de uma
função também através de parâmetros

Exemplo: protótipo de função com uma matriz
de dimensão variável como parâmetro
int soma2d(int lin, int col, int v[lin][col]);
 Ou omitindo o nome dos parâmetros
int soma2d(int, int, int [*][*]);
Os parâmetros que definem a dimensão
da matriz devem aparecer antes da
matriz na lista de parâmetros da função
28
O Qualificador const
 Você pode impedir que o conteúdo do
endereço de memória de um ponteiro seja
alterado através do qualificador const
 Por exemplo:
 void fun(const char * x);

 x é não pode alterar o conteúdo do endereço


que ele armazena
 Normalmente utiliza-se o const para evitar
que o conteúdo de vetores sejam alterados
na função, já que eles são passados
automaticamente por referência
29
Passando Argumentos para
main()

A função main() também pode receber
argumentos que são passados na
chamada ao programa

Forma geral:
int main(int argc, char * argv[]) {
...
}

argc: indica o número de argumentos

argv: vetor de string com os argumentos

O 1o argumento é o nome do programa
30
Exemplo: imprimindo os
argumentos da main()
#include <stdio.h>
int main(int argc, char * argv[]) {
int i;
printf("Argumentos da main():\n");
for(i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}

31
Classes de Armazenamento


Determina em que pontos do programa ela
pode ser acessada, quando ela será criada e
quando será destruída, em que lugar ela
será armazenada e qual o seu valor inicial

São quatro as classes de armazenamento
em C:

auto (automáticas)

extern (externas)

static (estáticas)

register (em registradores)
32
Classes de Armazenamento


A classe auto

São visíveis ou acessíveis somente às funções em
que estão declaradas

A palavra reservada auto pode ser usada para
especificar uma variável automática, mas não é
necessária, visto que a classe auto é default

São criadas em tempo de execução

São destruídas ao término da execução do bloco
ao qual pertencem

Não são inicializadas com nenhum valor
específico

33
Classes de Armazenamento


A classe extern

Ao contrário de variáveis automáticas,
declaradas dentro das funções, as
variáveis externas são declaradas fora de
qualquer função

A instrução de declaração de uma variável
externa é idêntica à de uma variável
automática

A acesso a elas é permitido a todas as
funções definidas após a sua declaração, e
elas existirão enquanto o programa estiver
sendo executado 34
Classes de Armazenamento


...A classe extern

São criadas em tempo de compilação

São inicializadas com zero por falta de
inicialização explícita

A palavra reservada extern não é usada
para criar variáveis da classe extern e sim
para informar ao compilador que a
variável em questão foi criada em outro
programa compilado separadamente e
que será linkeditado junto a este para
formar o programa final
35
Classes de Armazenamento


A classe static

As variáveis da classe static por um lado
se assemelham às automáticas, pois são
conhecidas somente das funções que as
declaram, e por outro lado se assemelham
às externas, pois mantêm seus valores
mesmo quando a função termina

São criadas em tempo de compilação

São inicializadas com zero por falta de
inicialização explícita

36
Classes de Armazenamento


A classe register

Indica que a variável deve ser guardada
fisicamente numa memória de acesso
muito rápido chamada registrador

Basicamente, variáveis register são
usadas p/ aumentar a velocidade de
processamento

O programador deve escolher as variáveis
que são mais frequentemente acessadas e
declará-las como da classe register

Fortes candidatas a este tratamento são
as variáveis de laços e os argumentos de
funções 37
O Preprocessador

Programa que examina o código-fonte
em C e executa modificações nele antes
da compilação com base em instruções
chamadas diretivas

Diretivas seriam as instruções que o
preprocessador executa

Estão contidas no programa-fonte, mas não
do programa que compilamos

O preprocessador faz parte do
compilador e é executado
automaticamente antes da compilação
38
O Preprocessador


Já usamos a diretiva #include para
incluir arquivos de cabeçalho em nossos
programas

Conjunto de diretivas mais comum
 #define  #ifndef
 #undef  #else
 #include  #elif
 #if  #endif
 #ifdef  #error

39
O Preprocessador


As diretivas podem ser colocadas em
qualquer lugar do programa

Geralmente são escritas no início do
programa (antes da main) ou antes de uma
função em particular

Elas se aplicam somente do ponto onde
estão escritas ao final do programa-
fonte

40
A diretiva #define


Em sua forma mais simples é usada
para definir constantes simbólicas com
nomes apropriados

Exemplo: identificador
texto
#define PI 3.14

O nome que segue a palavra #define é
chamado identificador

A frase escrita após o identificador é
chamado texto
41
A diretiva #define


Quando o preprocessador encontra uma
diretiva, procura abaixo dela seu
identificador e o substitui pelo seu texto

Por convenção, o identificador é escrito
em letras maiúsculas

Não há ; após a diretiva

Cada diretiva deve ser escrita em uma
linha
42
A diretiva #define


Por meio da diretiva #define podemos
definir textos ou instruções completas
com um nome indicativo

Por exemplo:
#define ERRO fprintf(stderr,"\t\tERRO!\n")
...
if(zebra) ERRO;

43
Macros


Diretivas #define que aceitam
argumentos

Exemplo:
#define PRN(x) printf("%d\n",x)
...
PRN(n1); Será substituído por printf("%d\n",n1);

Na definição de uma macro não pode
haver espaço em branco no
identificador
44
O uso de parênteses em
macros

A falta de parênteses em macros pode
provocar erros consideráveis

Exemplo:
#define SOMA(x,y) x + y
...
z = 10 * SOMA(3,4); z = 10 * 3 + 4;

Solução:
#define SOMA(x,y) (x + y)

45
O uso de parênteses em
macros

Parênteses envolvendo o texto não
solucionam todos os problemas

Exemplo:
#define PROD(x,y) (x * y)
...
z = PROD(2+3, 4); z = (2 + 3 * 4);

Solução:
#define PROD(x,y) ((x) * (y))

46
Definindo macros usando
outras macros

Uma macro pode ser definida usando
outra macro

Por exemplo:
#define PI 3.14
#define SQ(x) ((x) * (x))
#define AREA(x) (PI * SQ(x))

47
Macros versus Funções


Macros

Simples substituições dentro do programa

Execução mais rápida

Código do programa aumentado

O tipo de argumentos em macros não é
validado (vantagem?)

48
Referências

SCHILDT, Herbert. C Completo e Total. 3. ed.,
Makron Books, 1997.

MIZRAHI, Victorine Viviane. Treinamento em
linguagem C: [curso completo em um
volume]. 2. ed. São Paulo: Pearson Prentice
Hall, 2008.

DEITEL, M.H.; DEITEL, P.J.. Como Programar
em C. 2. ed., LTC, 1999.

PRATA, Stephen. C Primer Plus. 6. ed.,
Addison Wesley, 2014.
49

Você também pode gostar