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. 2 Funções • 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. 3 Definição Geral • Uma função deve ser definida conforme o esquema abaixo: ESPEC-DECLARAÇÃO ID( DECL-ID-1, ..., DECL-ID-n ) { CORPO_FUNÇÃO } 4 Definição Geral • 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. 5 Definição Geral • 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 ou extern) • O tipo de acesso ( const ou volatile ) 6 Definição Geral • O CORPO_FUNÇÃO consiste em DECLARAÇÕES de VARIÁVEIS com escopo LOCAL seguidas de COMANDOS. • Caso o tipo de dados constante nos ESPECDECLARAÇÃO seja diferente de void, deve haver ao menos um comando return ...; no CORPO_FUNÇÃO. 7 Definição de Função (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 } 8 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. 9 Declaração de Funções: Protótipos • 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, ..., ESPECDECL-n ); 10 Declaração de Funções: Protótipos • 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(); 11 Um função f() é diferente de f(void) ! • Um função declarada como: • int 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(); 12 Um função f() é diferente de f(void) ! • 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. 13 Exemplo de Funções -‐ Primo #include <stdio.h> #include <math.h> int primo(int num) { int div; num = abs(num); if (num > 2) { for (div = 3; div<sqrt(num); div++) if (num % div == 0) return 0; } return 1; } 14 Chamando a função primo //a função primo está declarada antes de main int main() { int numero; scanf(“%d”, &numero); if (primo(numero)) prinM(“O numero %d é primo”, numero); else prinM(“O numero %d não é primo”, numero); } 15 Modelo código completo #include <stdio.h> #include <math.h> int primo(int num); int main() { int numero; scanf(“%d”, &numero); if (primo(numero)) prinM(“O numero %d é primo”, numero); else prinM(“O numero %d não é primo”, numero); } int primo(int num) { int div; num = abs(num); if (num > 2) { for (div = 3; div<sqrt(num); div++) if (num % div == 0) return 0; } return 1; } Primo declarada antes de usar Escrita em qualquer lugar 16 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. 17 Chamada de Função 18 Exemplo: CHAMADA por VALOR unsigned int modulo(int x) { if (x < 0) return x*-‐1; return x; } int main () { int a = -‐ 2, ma = modulo(a); prinM("| %d | = %d\n", a, ma); } 19 Exemplo: simulando CHAMADA por REFERÊNCIA unsigned modulo(int * x) { if (*x < 0) return (*x) * (-‐1); return *x; } int main () { int a = -‐ 2, ma = a; modulo(&ma); prinM("| %d | = %d\n", a, ma); } 20 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. • 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. 21 Chamadas de Funções com Arranjos // *str não deve ser modificado no interior de strlen int strlen(const char str[]) { int i; for(i =0; *str; i++, str++); } return i; 22 Chamadas de Funções com Arranjos /*str1 deve ser modificada no interior de strlen já, *str2 não */ int strcpy(char * str1, const char * str2) { int i = 0; do{ str1[i] = str2[i]; }while ( str2[i++] ); } return i - 1; 23 Main main() A função main() • O que main() devolve? • De acordo com o padrão ANSI, a função main() devolve um inteiro para o processo chamador, que é, geralmente, o sistema operacional. • Devolver um valor em main() é equivalente a chamar exit() com o mesmo valor. A função main() • Se main() não devolve explicitamente um valor, o valor passado para o processo chamador é tecnicamente indefinido. • Na prática, a maioria dos compiladores C devolve 0, mas não conte sempre com isso! • Pode-se também declarar main() como void. Alguns compiladores geram uma ADVERTENCIA, se a função não é declarada como void e também não devolve um valor. argc e argv argc e argv 1. int main ( int argc, char * argv[] ) { 2. 3. for( ; argc -‐-‐ ; ) 4. prinM("arg[%d] = %s\n", argc, argv[argc]); 5. } argc e argv Lista de Parâmetros Variáveis 30 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. 31 va_arg(), va_start() e va_end() 32 va_arg(), va_start() e va_end() 33 va_arg(), va_start() e va_end() 34 va_arg(), va_start() e va_end() 35