<Tipo> <Ident> ( <lista-de-parâmetros> ) { <comandos> }
int NumDiasMes(int mes, int ehAnoBisexto) { int dias = 0; switch (mes) { case 4: case 6: case 9: case 11: dias = 30; break; case 2: dias = ehAnoBisexto ? 29 : 28; break; default: dias = 31; } return (dias); } int LeiaMes() { int numMes; printf("Digite o numero do mes:"); scanf("%d", &numMes); return (numMes); } int LeiaBisexto() { printf("Eh ano bisexto (digite 0 ou 1):"); int bisexto; scanf("%d", &bisexto); return (bisexto); } main() { int mes = LeiaMes(); printf("Num de dias do mes: %d", NumDiasMes(mes, mes==2 ? LeiaBisexto() : 0)); }
A passagem de parâmetros padrão de C é por valor. Sendo assim, qualquer alteração no valor dos parâmetros dentro da função não provoca qualquer alteração nas variáveis que porventura forem passadas como parâmetro na chamada de uma função.
Exemplo: função que tenta trocar valores de variáveis, mas não consegue.
void troca(int a, int b) { int t = a; a = b; b = t; } main() { int a = 1, b = 2; printf("antes: a = %d e b = %d\n", a, b); // mostra 1 e 2 troca(a, b); printf("depois: a = %d e b = %d", a, b); // mostra 1 e 2 }
A função acima não consegue trocar o valor dos parâmetros passados porque os parâmetros são passados por valor. Sendo assim, seus valores são cópias dos valores das variáveis passadas. Daí as alterações não terem efeito nas variáveis de origem.
Para cada posição de memória é associado um número inteiro chamado endereço da posição de memória. Como uma variável é alocada em uma posição de memória, a cada variável é associado um endereço. Um ponteiro é uma variável capaz de armazenar um endereço de outra variável, sendo declarado com a seguinte sintaxe:
<tipo-do-dado> *<identificador>;
Essa declaração indica que o identificador é o nome da variável do tipo apontador. Nesta variável é armazenado um endereço de uma variável do tipo tipo-do-dado. Por exemplo, uma declaração do tipo int *p; indica que p é uma variável capaz de armazenar o endereço de uma variável do tipo int. Na prática dizemos que p aponta para um inteiro. Assim, ponteiros também são chamados apontadores. Como ponteiros são variáveis, pode-se atribuir um ponteiro a outro do mesmo tipo. Por exemplo, são válidas as seguintes instruções:
int *p, *t, i; p = &i; t = p;
O operador de endereço & fornece o endereço da variável ao qual é associado. Deste modo, p receberá o endereço de i o que também acontecerá com t quando da execução do comando t = p. Se p é um ponteiro, a indicação *p num programa acessa o conteúdo da variável para a qual p aponta.
Exemplo: função que troca valores de variáveis.
void troca(int *a, int *b) { int t = *a; *a = *b; *b = t; } main() { int a = 1, b = 2; printf("antes: a = %d e b = %d\n", a, b); // mostra 1 e 2 troca(&a, &b); printf("depois: a = %d e b = %d", a, b); // mostra 1 e 2 }
A linguagem C suporta funções recursivas. Um exemplo é o fatorial de um número.
Exemplo: fatorial implementado de forma recursiva.
long Fatorial(int n) { if ((n == 0) || (n == 1)) return (1); else return (n * Fatorial(n - 1)); }