Buscar

02 Subprogramas em C Parte 1 - Conceitos Básicos

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

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

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ê viu 3, do total de 8 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

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

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ê viu 6, do total de 8 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

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

Prévia do material em texto

1 
LINGUAGEM E TÉCNICA DE PROGRAMAÇÃO I 
 
Profa. Gisele Busichia Baioco 
gisele@ft.unicamp.br 
 
 
Modularização de Programas 
 
Subprogramas em C 
Parte 1 – Conceitos Básicos 
1 Introdução 
Em C, os subprogramas são todos classificados como funções, sendo que os 
procedimentos são considerados como funções que não retornam valores. Na realidade um 
programa C é todo composto por funções, inclusive o main() é uma função. 
O objetivo de se utilizar funções é a modularização de programas, pois as funções 
dividem grandes tarefas computacionais em tarefas menores. Além disso, o uso de funções: 
• permite que programadores utilizem o que outros programadores já 
implementaram ao invés de partir da estaca zero; 
• evita que o programador tenha que escrever o mesmo código repetidas vezes. Por 
exemplo, suponha que exista em um programa uma operação onde se calcula o 
quadrado de um número. Se mais adiante no mesmo programa for necessário 
realizar a mesma operação, a solução mais direta seria escrevê-la novamente. 
Entretanto, com o uso de funções, basta escrever uma seção de código para 
calcular o quadrado de um número qualquer e usá-la em todos os pontos do 
programa que é necessário calcular o quadrado. 
Assim, uma função em C é uma unidade de código de programa autônoma, desenhada 
para cumprir uma tarefa particular. 
É importante observar que a chamada de uma função aumenta o tempo de execução de 
um programa. Entretanto, na maioria das aplicações, esse custo adicional de tempo de 
execução é deixado de lado pelos outros benefícios trazidos pelo uso de funções (legibilidade, 
reutilização de código, facilidade de manutenção etc). Assim, o uso de funções só deve ser 
evitado quando o tempo de execução for realmente primordial. 
2 Declaração de funções em C 
Sintaxe de declaração de uma função em C: 
 
 tipo-de-retorno nome-da-função(lista-de-parâmetros) 
 { 
 corpo-da-função 
 } 
 
onde: 
tipo-de-retorno: é opcional e especifica o tipo do valor que a função retornará. Caso o 
tipo não tenha sido especificado, por default (padrão) a função retornará um resultado inteiro 
(tipo int). 
 nome-da-função: qualquer identificador válido em C. 
 2 
lista-de-parâmetros: é opcional e consiste de uma lista composta por tipos de dados e 
nomes de variáveis, que são os parâmetros da função, separados por vírgula. Sintaxe: 
 
tipo-de-dado nome-do-parâmetro1, ..., tipo-de-dado nome-do-parâmetroN 
 
corpo-da-função: consiste da implementação da função. É nele que as entradas são 
processadas, saídas são geradas ou outras coisas são feitas. 
 
Deve-se observar que uma função não terá que ter obrigatoriamente uma lista de 
parâmetros e nem sempre devolverá um valor. Um tipo void deve ser utilizado para funções 
que não retornam valor. 
 
Exemplos: 
 
 /* Declaração da função soma, que retorna o resultado da soma de 
 seus parâmetros */ 
 float soma(float x, float y) 
 { 
 return (x+y); 
 } 
 
 /* Declaração da função imprime_soma, que imprime o resultado da soma 
 de seus parâmetros na tela, não retornando valor */ 
 void imprime_soma(float x, float y) 
 { 
 printf(“%f”, x+y); 
 } 
3 Protótipos de Funções 
Protótipo de função é a definição de uma função, declarando o tipo e o número de 
parâmetros da mesma. Protótipos de funções devem ser colocados perto do início do 
programa, antes do main(), para que o compilador possa fazer as verificações de tipo de 
retorno e tipos de parâmetros das chamadas das funções que, em sua maioria estarão dentro 
do main(). As declarações das funções ficam, então, após o main(). 
Sintaxe de protótipos de funções em C: 
 
tipo-de-retorno nome-da-função(lista-de-tipos-dos-parâmetros); 
 
Exemplos: 
 
 #include <stdio.h> 
 
 /* Protótipos de funções */ 
float soma(float, float); 
void divide(float, int); 
 
main() 
 { 
 float prim, seg, res; 
 int terc; 
 prim = 10.5; 
 seg = 9.4; 
 terc = 3; 
 res = soma(prim, seg); /* Chamada da função soma */ 
 printf("%f\n", res); 
 3 
 divide(seg, terc); /* Chamada da função divide */ 
 } 
 
 /* Declaração da função soma, que retorna o resultado da soma de seus 
 parâmetros */ 
float soma(float x, float y) 
 { 
 return (x+y); 
 } 
 
 /* Declaração da função divide, que imprime na tela o resultado da 
 divisão de seu segundo parâmetro pelo primeiro, não retornando 
 valor */ 
 void divide(float a, int b) 
{ 
 printf("%f\n", a/(float)b); 
 } 
 
Os protótipos de funções foram acrescentados pela comissão do padrão ANSI C, para 
permitir que C faça uma verificação forte de tipos, parecida com a do Pascal. Isso faz com que 
o compilador emita mensagens de erros quando não há coincidência de tipos entre os 
argumentos da função chamada e os parâmetros declarados. 
4 O Comando return 
O comando return é utilizado para interromper a execução de uma função e voltar 
para a parte do código que a chamou, retornando ou não um valor. 
Suponha que uma função está sendo executada. Quando se chega a um comando return a 
função é encerrada imediatamente e, se o valor de retorno é informado, a função retorna esse 
valor. 
4.1 Retorno de uma função 
 O retorno de uma função sem nenhum valor pode ser executado de duas maneiras: 
• o computador executa o último comando da função e depois encontra } que 
significa o fim da função; 
• usando o comando return sozinho, sem nenhum valor associado a ele. 
Sintaxe do comando return, sem nenhum valor associado: 
 
 return; 
4.2 Valores de retorno 
 Quando usado para retornar um valor, o comando return tem a seguinte sintaxe: 
 
return valor-de-retorno; 
 
É importante lembrar que o valor de retorno fornecido tem que ser compatível com o 
tipo de retorno declarado para a função. 
Na chamada de um função, pode-se atribuir valores de retorno da função a uma 
variável, mas uma função não pode ser objeto de uma atribuição. Exemplos: 
 
 x = abs(y) /* comando coreto */ 
 swap(x,y) = 100 /* comando incorreto */ 
 
 4 
 No segundo exemplo, haverá um erro de compilação. 
 Embora todas as funções que não sejam do tipo void retornem valores, pode-se criar 
funções de dois tipos: 
• computacional: função criada especificamente para efetuar operações em seus 
argumentos e devolver um valor com base naquelas operações. Por exemplo, as 
funções de biblioteca sqrt() e sin(), que devolvem a raiz quadrada de um número e seu 
seno, respectivamente. 
• função que manipula informações e cujo valor retornado indica o sucesso ou o 
fracasso da mesma: por exemplo, a função fwrite(), usada para gravar informações em 
um arquivo em disco e que devolve o número de bytes caso a gravação seja bem 
sucedida e qualquer outro valor caso contrário. 
 
O valor retornado por uma função pode não ser utilizado. Por exemplo, a função 
printf() retorna o número de caracteres impressos, porém não seria comum encontrar um 
programa que realmente verificasse esse valor de retorno. 
4.3 Exemplos da utilização de return 
#include <stdio.h> 
 
/* Protótipo da função */ 
int quadrado(int); 
 
main() 
{ 
 int num; 
 printf ("Entre com um numero inteiro: "); 
 scanf ("%d",&num); 
 num = quadrado(num); 
 printf("\nO seu quadrado vale: %d",num); 
} 
 
/* Declaração da função quadrado que retorna o valor do quadrado de um 
 número inteiro passado como parâmetro */ 
int quadrado(int a) 
{ 
 return(a*a); 
} 
 
#include <stdio.h> 
 
/* Protótipo da função */ 
int par(int); 
 
main() 
{ 
 int num; 
 printf ("Entre com numero inteiro: "); 
 scanf ("%d",&num); 
 if (par(num) == 1) 
 printf ("\nO numero e par."); 
 else 
 printf ("\nO numero e impar."); 
} 
 
 
 5 
/* Declaração da função par, que retorna 1 se o valor passado como 
 parâmetro é par e 0 caso contrário */ 
int par(int a) 
{ 
 if (a%2 == 0) /* Verifica se a é divisível por dois */ 
 return 1; /* Retorna 1 se for divisível – é par */ 
 else 
 return 0; /* Retorna0 se não for divisível – não é par */ 
} 
 
Como pode ser observado, no último exemplo uma função pode ter vários comandos 
return. 
5 O Tipo Void 
Em inglês, void quer dizer vazio e é isto mesmo que o void é. Ele permite fazer 
funções que não retornam nenhum valor e funções que não têm parâmetros. 
Uma função que não retorna nenhum valor é similar a um procedimento. Pode-se 
agora escrever o protótipo de uma função que não retorna valor algum: 
 
void nome-da-função(lista-de-prâmetros); 
 
Em uma função como a anterior, não existe valor de retorno em return. Aliás, neste 
caso, o comando return não é necessário na função. 
 Pode-se também fazer funções que não têm parâmetros: 
 
tipo-de-retorno nome-da-função(void); 
 
ou, ainda, funções que não tem parâmetros e não retornam nada: 
 
void nome-da-função(void); 
 
Um exemplo de funções que usam o tipo void: 
 
#include <stdio.h> 
 
void mensagem (void); 
 
main () 
{ 
 mensagem(); 
 printf ("\nDiga de novo:\n"); 
 mensagem(); 
} 
 
void mensagem (void) 
{ 
 printf ("Ola! Eu estou vivo.\n"); 
} 
 
Deve-se lembrar agora que a função main() é uma função. O compilador acha que a 
função main() deve retornar um inteiro. Isso pode ser interessante caso se deseje que o 
sistema operacional receba um valor de retorno da função main(), considerando a seguinte 
 6 
convenção: se o programa retornar zero, significa que ele terminou normalmente, e, se o 
programa retornar um valor diferente de zero, significa que o programa teve um término 
anormal. Caso não seja necessário o retorno de main(), basta declara-lo como void. 
 As duas funções main() abaixo são válidas: 
 
main() /* ou int main() ou int main(void) */ 
{ 
 ... 
 return 0; 
} 
 
void main() /* ou void main(void) */ 
{ 
 ... 
} 
 
A primeira opção é válida pois, como já visto anteriormente, as funções em C têm por 
default retorno inteiro. Alguns compiladores podem reclamar da segunda opção, dizendo que 
main() sempre deve retornar um inteiro. Se isto acontecer basta utilizar a primeira opção. 
6 Escopo de Variáveis 
As regras de escopo determinam quais variáveis são acessíveis dentro de um certo 
trecho do programa e estabelecem o tempo de vida (tempo em que uma variável fica alocada 
na memória) das mesmas. Além disso, pode-se dizer que o código e os dados que são 
definidos dentro de uma função não podem interagir com o código e dados que são definidos 
em outra função, pois seus escopos são diferentes. 
De acordo com as regras de escopo de C, existem três tipos de variáveis: variáveis 
locais, parâmetros formais e variáveis globais. 
6.1 Variáveis locais 
 As variáveis locais são aquelas definidas dentro de uma função ou dentro de um bloco 
de código. Logo, essas variáveis serão conhecidas apenas dentro da função ou do bloco de 
código onde foram declaradas. Exemplo: 
 
 void f() 
 { 
 char ch; /* esta variável só é criada na função f */ 
 printf("continua? (S/N):"); 
 ch = getche(); 
 if (ch == 'S') /* segue apenas se a resposta for 'S' */ 
 { 
 char s[80]; /* esta variável só é criada neste bloco */ 
 printf("Digite seu nome: "); 
 gets(s); 
 } 
 } 
 
 Desse modo, as variáveis são criadas (alocadas na memória) na entrada da função ou 
do bloco de código e destruídas (desalocadas da memória) na saída. Conseqüentemente, seu 
conteúdo é perdido quando a execução da função ou do bloco termina. 
 7 
6.2 Parâmetros formais 
Os parâmetros formais são especificados na declaração das funções. Esses parâmetros 
são as variáveis que aceitarão os valores dos argumentos (ou parâmetro reais) que são 
passados na chamada de uma função. 
Exemplo: 
 
 main() 
 { 
 int a, b, res; 
 ... 
 res = func(a, b); /* a e b são argumentos ou parâmetros reais */ 
 ... 
 } 
 
 int func(int s, int c) /* s e c são parâmetros formais */ 
 { 
 return (s*c); 
 } 
 
 Os parâmetros formais são desconhecidos quando a execução da função termina. 
 Atenção: deve-se verificar sempre se os parâmetros formais declarados são do mesmo 
tipo dos argumentos que usados para chamar a função. 
6.3 Variáveis globais 
 As variáveis globais são declaradas fora de qualquer função C e são conhecidas e 
acessíveis em todo o programa, pois fica alocada na memória durante toda a execução do 
programa. 
 Caso uma variável local e uma global tenham o mesmo nome, todas as referências 
aquele nome dentro da função na qual a variável local estiver declarada, estarão ligadas à 
variável local e não terão nenhum efeito sobre a variável global. 
 Sempre que possível deve-se utilizar outro tipo de variável, pois as variáveis globais 
têm as seguintes desvantagens: 
• ocupam memória durante toda a execução do programa e não apenas quando são 
necessárias; 
• o uso de uma variável global, quando é viável a utilização de uma local, torna a 
função menos generalizada; 
• o uso de muitas variáveis globais pode levar a programação a erros por causa de 
efeitos colaterais desconhecidos e indesejados. 
6.4 Exemplo geral de escopo 
 /* um programa com vários escopos */ 
 
int cont /* variável global */ 
 
void func(int); /* protótipo de func */ 
 
main() 
 { 
 int s; /* local a main() */ 
 8 
 func(s); 
 } 
 
 void func(int r) /* r é o parâmetro formal de func */ 
 { 
 if (r) 
 { 
 int a, b; /* locais ao bloco if dentro de func */ 
 ... 
 } 
 ... 
 } 
7 Exercícios de Fixação 
1. Fazer uma função C que calcule e imprima na tela a média aritmética de dois números. 
Fazer um programa C para testar a função. 
2. Fazer uma função C que calcule e retorne um número inteiro elevado a qualquer potência 
(inteira). Fazer um programa C para testar a função. 
3. Fazer uma função C que determine e retorne o maior de três lados de um triângulo passados 
como parâmetros. Fazer um programa C para testar a função. 
4. Um número é primo se for divisível apenas por si próprio e por 1. Fazer uma função 
primo(int num) para verificar se um número passado como parâmetro é primo. A função 
deve retornar 1 se o número for primo e 0 caso contrário. Em seguida fazer uma função 
divisor(int a, int b) que verifica se b é divisor de a (b é divisor de a se o resto da 
divisão de a por b é zero). A função deve retornar 1 se b for divisor, caso contrário deve 
retornar zero. Usando as duas funções construídas, fazer um programa C para determinar os 
divisores primos de um número. 
5. Estude o seguinte programa e aponte o valor de cada variável sempre que solicitado: 
 
#include <stdio.h> 
 
int num; 
 
int func(int, int); 
 
main() 
{ 
int first = 0, sec = 50; 
 num = 10; 
 num = num + func(first, sec); /* Qual é o valor de num, first e séc 
 antes e depois da atribuicao? */ 
 printf("\nConfira: num = %d first = %d sec = %d",num, first, sec); 
} 
 
int func(int a, int b) 
{ 
 a = (a+b)/2; /* Qual é o valor de a apos a atribuição? */ 
 num = num - a; 
 return a; 
}

Outros materiais