11. Funções

return-type function-name(argument list)
{
    statements
}

No exemplo

int minimum(int a, int b)
{
    if (a < b)
        return a;
    else
        return b;
}

a função tem o nome minimum, devolve um valor do tipo int, tem dois parâmetros, ambos do tipo int.

Os parâmetros são escritos com uma sintaxe igual à declaração de variáveis. Separados por , (vírgula).

Se o return-type for omitido significa que a função devolve um valor do tipo int.

Para indicar que a função não tem valor associado, deve colocar-se a palavra void no lugar do tipo de retorno.

void delay(int cicles)
{
    while (cicles--)
        ;
}

A lista de parâmetros também pode ser omitida. Neste caso o significado é que a função não recebe argumentos. (Nem sempre foi assim, em versões antigas tinha outro significado.)

Pode colocar-se void no lugar da lista de parâmetros para explicitar que a função não recebe argumentos.

int delay_5_seconds(void);
Relativamente a outras linguagens de programação, na linguagem C:
  • a passagem de argumentos é posicional – não existe passagem de argumentos nomeados;

  • não existe sobrecarga de funções – não se podem redefinir funções com o mesmo nome;

  • não existem argumentos por omissão.

11.1. Array como parâmetro

Considere-se a seguinte função que verifica se um array de inteiros contém um dado valor.

bool contains(int array[], int array_size, int value)
{
    bool result = false;
    int i = 0;
    while (i < array_size) {
        if (array[i] == value) {
            result = true;
            break;
        }
        i++;
    }
    return result;
}

Conside-se o seguinte programa de teste da função contais.

int numbers[] = {45, 25, 50, 55, 57, 85};

bool has_five;

int main()
{
   has_five = contains(numbers, 6, 5);
}

Na declaração de um parâmetro de função do tipo array não se indica a dimensão do array. É o caso de int array[] em contains.

bool contains(int array[], int array_size, int value);

Formalmente pode figurar, mas é ignorada pelo compilador, não tem qualquer efeito.

bool contains(int array[333], int array_size, int value);

Na passagem de um array como argumento de função, apenas é passada a informação sobre o endereço inicial do array em memória. No interior de uma função não há maneira de obter a dimensão de um array que está a ser recebido em parâmetro. Algo como array.length não existe em linguagem C. Essa é a justificação para a existência do segundo parâmetro array_size na função contains.

Na linguagem C, um array como parâmetro é sempre acompanhado de outro parâmetro ou de algum artifício que permita operar o array dentro dos seus limites.

No caso das funções que manipulam strings, que são suportadas por arrays de caracteres, a informação de dimensão está no termindador da string – valor zero após o último caractere da string.

Na função strcmp a sub-expressão str1[i] != 0 serve para não se ultrapassar os limites dos arrays. Esta sub-expressão só será avaliada como falsa se as strings forem iguais.

int strcmp(const char str1[], const char str2[])
{
   for (int i = 0; str1[i] != 0 && str1[i] == str2[i]; ++i)
      ;
   return str1[i] - str2[i];
}

O método de utilizar um valor marcador para indicar o final do array só pode ser aplicado se o marcador não for um valor de dados possível.

11.2. Parâmetros constantes

A utilização da palavra const na declaração de parâmetros significa que os argumentos não podem ser modificados durante a execução da função. No caso de arrays, significa que o conteúdo do array não pode ser alterado.

Sem o atributo const os parâmetros de funções são como variáveis locais.

1int f(const char string[], int i)
2{
3   if (string[i] != '\0')
4      string[i] += ' ';
5   i += 3;
6}

No exemplo, a tentativa de alteração do conteúdo de string na linha 4 é assinalada com erro pelo compilador.

A instrução da linha 5 adiciona 3 ao parâmetro i, como se fosse uma variável local.