[CAPÍTULO 1] - [CAPÍTULO 2] - [CAPÍTULO 3]
Funções: definição, declaração e chamada
Funções:
Em C, um programa é uma coleção de FUNÇÕES. Uma função é um bloco de código que recebe um nome e que tem possivelmente PARÂMETROS. A partir do nome, o bloco de código que forma a função pode ser chamado. CHAMAR uma função significa iniciar a execução de um bloco de código. Caso a função possua parâmetros, durante a CHAMADA dela devem ser indicados ARGUMENTOS que são valores ou variáveis que irão corresponder aos parâmetros da função. Ao final da execução, uma função pode ainda retornar um valor para o código que fez a chamada da função.Definição de Função: Forma Geral
Uma função deve ser definida conforme o esquema abaixo:ESPEC-DECLARAÇÃO ID( DECL-ID-1, ..., DECL-ID-n ) { CORPO_FUNÇÃO }
ID
define o nome da função. A lista de declarações DECL-ID-1, ..., DECL-ID-n
é dita LISTA de PARÂMETROS da função. Cada ID-i
consiste em uma variável com escopo local na função e que irá receber, como valor inicial, o valor passado como ARGUMENTO durante a chamada da função.Se pensarmos no ID de uma função como uma VARIÁVEL GLOBAL, os
ESPEC-DECLARAÇÃO
definem que características tem este ID:- O tipo de dados (
void
,int
,char *
, ... ) - Classe de armazenamento (
static
ouextern
) - O tipo de acesso (
const
ouvolatile
)
O
CORPO_FUNÇÃO
consiste em DECLARAÇÕES de VARIÁVEIS com escopo LOCAL seguidas de COMANDOS. Caso o tipo de dados constante nos ESPEC-DECLARAÇÃO
seja diferente de void
, deve haver ao menos um comando return ...;
no CORPO_FUNÇÃO
.Definição de Função: Formato Antigo
Por questões de compatibilidade, uma função pode ainda ser definida seguindo o formato originalmente proposto pelos projetistas da linguagem. Neste formato original, o que muda é a forma de se especificar os parâmetros da função:ESPEC-DECLARAÇÃO ID( ID-1,...,ID-n ) DECL-ID-1; ...; DECL-ID-n; { CORPO_FUNÇÃO }
Declaração de Funções: Protótipos
O ideal é que toda função, antes de ser usada, deve ser declarada. Caso a função encontra-se DEFINIDA no mesmo arquivo e em uma posição antes de seu uso, então a própria DEFINIÇÃO da função serve como DECLARAÇÃO da função. Caso contrário, a DECLARAÇÃO da função dever ser feita através de PROTÓTIPOS. Um protótipo é como se fosse um CABEÇALHO para a função, ou seja, o ID da função os ESPEC do tipo retornado pelo função e os ESPEC dos tipos de cada parâmetro da função:ESPEC-DECLARAÇÃO ID( ESPEC-DECL-1, ..., ESPEC-DECL-n );
Em uma situação onde uma função
f
esteja sendo usada sem ter sido antes declarada, então implicitamente o compilador declarada a função como sendo: int f();
Um função f() é diferente de f(void) !
Um função declarada comoint f();é diferente de uma função declarada como
int f(void);
No primeiro caso, o compilador não sabe se a função pode ou não receber argumentos durante a sua chamada. Quer dizer, é perfeitamente válido fazer:
int x = f(3.14); int y = f(2.7, 4); int z = f();
No segundo caso, o compilador é informado explicitamente que a função não deve receber nenhumar argumento. Assim, as duas primeiras linhas do código acima gerariam uma mensagem de erro e apenas a última seria considerada como válida.
Lista de Parâmetros Variável
Quando se quer especificar uma função que possui uma lista de parâmetros variável em número e tipo, deve-se terminar a declaração dos parâmetros utilizando três pontos...
Por exemplo:
void f(int a, char * b, ... );
Qualquer função que use um número variável de parâmetros deve ter ao menos um deles explicitamente declarado.
va_arg(), va_start() e va_end()
Chamada de Função
Chamar uma função significa iniciar a execução de seu corpo de código. Caso a função tenha sido declarada com PARAMETROS, durante a chamada deve ser passados ARGUMENTOS que correspondam em número e tipo com os PARAMETROS da função.PARAMETROS são variáveis locais à função que irão receber como valores iniciais os valores dos ARGUMENTOS utilizados na CHAMADA da função.
OBS.: Em C, as chamadas de função são feitas por VALOR. No entanto, o conceitos de chamada por referência pode ser simulado em C através do uso de apontadores.
Exemplo: CHAMADA por VALOR
unsigned modulo(int x) { x = x < 0 ? - x : x ; return x; } int main () { int a = - 2, ma = modulo(a); printf("| %d | = %d\n", a, ma); }Ao executar o programa acima, vc. irá perceber que o valor da variável
a
não é modificado pela função módulo. Ou seja, a variável a
e usada como ARGUMENTO em uma CHAMADA por VALOR de modulo()
. Exemplo: simulando CHAMADA por REFERÊNCIA
unsigned modulo(int * x) { *x = *x < 0 ? - *x : *x ; return *x; } int main () { int a = - 2, ma = a; modulo(&ma); printf("| %d | = %d\n", a, ma); }
Chamadas de Funções com ARRANJOS
O ID de vetores, matrizes e strings são conceitualmente apontadores para o primeiro elemento do arranjo. Assim, ao se usar o nome de vetores, matrizes ou strings em uma chamada de função está-se fazendo uma CHAMADA por REFERÊNCIA. Em outras palavras, vetores, matrizes ou strings quando passados como argumentos de funções e manipulados no interior dessas funções têm os seus valores modificados ao término da função (vide também: Matrizes e Parâmetros de Funções ).Para evitar que modificações acidentais ocorram com vetores, matrizes e strings passados como argumentos de funções deve-se declará-los utilizando o qualificador
const
.Exemplos:
/* *str não deve ser modificado no interior de strlen */ int strlen(const char str[]) { int i; /* str[0] = 'a'; - qualquer tentativa de modificar o conteúdo da string apontada por str irá gerar uma mensagem de erro ! */ for(i =0; *str; i++, str++); return i; } /* *str1 deve ser modificada no interior de strlen já, *str2 não */ int strcpy(char * str1, const char * str2) { int i = 0; /* str2[0] = 'a'; - qualquer tentativa de modificar o conteúdo da string apontada por str2 irá gerar uma mensagem de erro ! */ do str1[i] = str2[i]; while ( str2[i++] ); return i - 1; }
Leituras Recomendadas
- CCT cap 6
- K&R
Exercícios
Obs.: Nos exercícios abaixo, escolha cinco e para estes mostre como as funções ficam quando definidas utilizando o formato antigo de definição de funções.- Em C, qual a diferença entre DECLARAÇÃO e DEFINIÇÃO de funções?
- O que significam:
- passagem de argumentos por valor?
- passagem de argumentos por referência?
- Escreva uma função que recebe um número inteiro n>0 e devolve o número de dígitos de n e o primeiro dígito de n.
- Escreva uma função que recebe como parâmetro um inteiro positivo ano e devolve 1 se ano for bissexto, 0 em caso contrário. (Um ano é bissexto se (ano % 4 = = 0 && (ano % 100 != 0 || ano % 400 = = 0)).)
- Escreva uma função que tem como parâmetros de entrada e saída três números inteiros, dia, mes e ano, representando uma data, e modifica esses inteiros de forma que eles representem o dia seguinte.
- Escreva um programa que leia um inteiro positivo n e uma seqüência de n datas e imprime, para cada data, o dia seguinte.
- Escreva uma função de cabeçalho
int divide (int *m, int *n, int d)
que recebe três inteiros positivos como parâmetros e devolve 1 se d divide pelo menos um entre *m e *n, 0 caso contrário. Fora isso, se d divide *m, divide *m por d, e o mesmo para o *n. - Escreva um programa que lê dois inteiros positivos m e n e calcula, usando a função acima, o mínimo múltiplo comum entre m e n, ou seja, mmc(m,n).
- Escreva uma função com protótipo
void somabit (int b1, int b2, int *vaium, int *soma);
que recebe três bits (inteiros entre 0 e 1) b1, b2 e *vaium e devolve um bit soma representando a soma dos três e o novo um bit "vai-um" em *vaium. - Escreva um programa que leia dois números em binário e calcula um número em binário que é a soma dos dois números dados. Utilize a função acima.
- Escreva uma função com o protótipo
void converte (char ch, int *tipo, char *valor);
que recebe um caractere ch e devolve em *tipo 0, se o caractere for um número inteiro, 1 se for uma letra (maiúscula ou minúscula) e 2 caso contrário; e além disso, no caso de ser uma letra, converte para maiúscula, senão devolve ch inalterado. - Escreva um programa que leia uma seqüência de n caracteres e imprima a seqüência convertida para maiúscula, eliminando os caracteres que não forem letras ou números.
- Escreva uma função que lê, linha a linha, uma matriz real Amxn
- Escreva uma função que imprime uma matriz real Amxn
- Escreva uma função que calcula a soma dos elementos da linha i de uma matriz real Amxn.
- Escreva uma função que calcula o produto dos elementos da coluna j de uma matriz real Amxn.
- Escreva uma função que troca o conteúdo de duas variáveis.
- Escreva uma função que recebe dois inteiros, i e j, uma matriz real Amxne troca linha i pela linha j. Utilize a função do item anterior.
- Um conjunto pode ser representado por um vetor da seguinte forma: V[0] é o tamanho do conjunto; V[1], V[2], etc. são os elementos do conjunto (sem repetições).
- Faça uma função chamada intersecção que dados dois conjuntos de números inteiros A e B, constrói um terceiro conjunto C que é a intersecção de A e B. Lembre-se de que em C[0] a sua função deve colocar o tamanho da intersecção.
- Faça um programa que lê um inteiro n > 1 e uma seqüência de n conjuntos de números inteiros (cada um com no máximo 100 elementos) e constrói e imprime um vetor INTER que representa a intersecção dos n conjuntos.
- Por exemplo, se n=3 e os conjuntos são {1, 2, 4, 9}, {2, 4, 7, 8, 9} e {5, 4, 9}, a entrada será:
3 O valor de n 4 V[0] = tamanho do primeiro conjunto 1 2 4 9 V[1] V[2] V[3] V[4] 5 V[0] = tamanho do segundo conjunto 2 4 7 8 9 V[1] V[2] V[3] V[4] V[5] 3 V[0] = tamanho do terceiro conjunto 5 4 9 V[1] V[2] V[3]
- E o vetor INTER construído será
INTER[0] = 2 tamanho do conjunto INTER[1] = 4 INTER[2] = 9 conjunto intersecção
- NOTE que não é preciso ler todos os conjuntos de uma só vez. Você pode ler os dois primeiros conjuntos e calcular a primeira intersecção. Depois, leia o próximo conjunto e calcule uma nova intesecção entre esse conjunto lido e o conjunto da intersecção anterior, e assim por diante. Use obrigatoriamente a função do item anterior, mesmo que você não a tenha feito.
Bibliografia e fonte:
- [CCT] Schildt, H. (1996) C, completo e total: 3a Ed.. São Paulo, Makron.
- LP, UFMA; Coutinho, Lucian. Linguagem de programação para ciencia da computação da ufma.http://www.deinf.ufma.br/~lrc/2009.1/LP/
- [K&R] KERNIGHAN, B. e RITCHIE, D. (1990) C, a linguagem de programação: padrão ANSI. Rio de Janeiro: Campus.
- DEITEL, H. M. (1999) Como programar em C. Rio de Janeiro: LTC.
- Módulo Consultoria e Informática (1989) Linguagem C: programação e aplicações. Rio de Janeiro: LTC.
Coloque aqui o seu email