Aqui está uma função que opera e retorna números de ponto flutuante que não precisam ser, necessariamente, inteiros. Ponto flutuante é uma maneira de representar um número como uma fração juntamente com uma potência de 2. (Para mais detalhes, veja .) Este exemplo calcula a média de três números de ponto flutuante que são passados para a função como argumentos:
Os valores dos parâmetros a, b e c não precisam ser inteiros e, mesmo quando são inteiros, provavelmente a média deles não o é.
double
é o tipo de dado usual em C para cálculos com números de ponto flutuante.
Para imprimir um double
com a função printf
, devemos usar '%f' em vez de '%d':
O código que chama a printf
deve passar um double
para impressão com '%f' e um int
para impressão com '%d'. Se o argumento tiver o tipo errado, a printf
produzirá uma saída sem sentido.
Aqui está um programa completo que calcula a média de três números específicos e imprime o resultado:
A partir de agora, não mostraremos mais exemplos de chamadas às funções que escrevemos na função main
. Em vez disso, encorajamos você a escrevê-las por conta própria quando quiser testar a execução de algum código.
Uma função para calcular a média de três números é muito específica e limitada. Uma função mais geral calcularia a média de qualquer quantidade de números. Isso requer passar os números em um array. Um array é um objeto na memória que contém uma série de valores do mesmo tipo de dado. Este capítulo apresenta os conceitos básicos e o uso de arrays através de um exemplo; para a explicação completa, veja .
Aqui está a definição de uma função para calcular a média de vários números de ponto flutuante, passados como tipo double
. O primeiro parâmetro, length
, especifica quantos números são passados. O segundo parâmetro, input_data
, é um array que contém esses números.
O código anterior introduz a expressão para se referir a um elemento de um array: input_data[i]
significa o elemento de índice i
no array input_data
. O índice do elemento pode ser qualquer expressão com um valor inteiro; neste caso, a expressão é i
. Veja .
O menor índice válido em um array é 0, não 1, e o maior índice válido é um a menos que o número de elementos. (Isso é conhecido como indexação com origem zero.)
Este exemplo também introduz a maneira de declarar que um parâmetro de função é um array. Tal declaração é feita após o nome do parâmetro. Assim como double foo
declara que foo
é do tipo double
, double input_data[]
declara que cada elemento de input_data
é do tipo double
. Portanto, input_data
em si tem o tipo "array de double".
É muito comum em textos técnicos em inglês você encontrar as palavras foo, bar ou foobar. Elas são utilizadas para passar uma ideia de "qualquer coisa", ou "qualquer nome", ou seja, a ideia de que o nome não importa. Em português, seria equivalente ao modo como nos referenciamos a pessoas desconhecidas com "fulano" ou "cicrano".
Ao declarar um parâmetro que é um array, não é necessário dizer qual é o comprimento do array. Neste caso, o parâmetro input_data
não tem informação de comprimento. É por isso que a função precisa de outro parâmetro, length
, para que o chamador forneça essa informação para a função avg_of_double
.
O nome avg_of_double é uma forma abrevidada de average of double. Em inglês, average é média. Já length, traduz para tamanho (no caso do código de exemplo, tamanho do array -em outras palavras, o número de elementos do array). Temos também input_data (dados de entrada) e sum (soma).
Até agora, apresentamos programas que operam com inteiros. Neste capítulo, apresentaremos exemplos de manipulação de números não inteiros e arrays de números.
O código para chamar a função avg_of_double
tem duas declarações que começam com o mesmo tipo de dado:
Em C, você pode combinar as duas, assim:
Isso declara nums_to_average
para que cada um de seus elementos seja um double
, e average
para que seja simplesmente um double
.
No entanto, embora você possa combiná-las, isso não significa que deva. Se for útil escrever comentários sobre as variáveis, e geralmente é, então é melhor manter as declarações em linhas separadas para que você possa colocar um comentário em cada uma. Isso também ajuda ao usar editores de texto para encontrar ocorrências de uma variável nos arquivos de código-fonte.
Em arquivos grandes de código-fonte, pode ser que você queira encontrar o momento da declaração de uma variável utilizando um editor de texto como vim, Visual Studio Code, Notepad++, etc. Por exemplo, você pode buscar por int num
para buscar a declaração de uma variável chamada num
, que é tipo int
. No entanto, se você declarar mais de uma variável na mesma linha como em int i, num, j;
, a busca por int num
não encontraria esta ocorrência. Além da clareza, este é o motivo pelo qual os autores desencorajam este tipo de declaração.
Definimos então todos os elementos do array nums_to_average
com atribuições, mas é mais conveniente usar um inicializador na declaração:
O inicializador do array é uma lista de valores separados por vírgulas, delimitados por chaves. Veja .
Note que a declaração não especifica um tamanho para nums_to_average
, então o tamanho é determinado a partir do inicializador. Há cinco valores no inicializador, então nums_to_average
recebe o comprimento 5. Se adicionarmos outro elemento ao inicializador, nums_to_average
terá seis elementos.
Como o código calcula o número de elementos a partir do tamanho do array, usando sizeof
, o programa operará em todos os elementos no inicializador, independentemente de quantos sejam.
No código de exemplo, uma certa aritimética é utilizada para pegar o tamanho do array, que é 5, já que este é inicializado com 5 elementos. A técnica consiste em utilizar o operador sizeof
, que retorna o tamanho de um tipo em tempo de compilação, diretamente no array e dividir esse resultado pelo tamanho de qualquer um dos elementos do array, já que todos são do mesmo tipo (normalmente o primeiro elemento, de índice 0, é o escolhido).
Para entender como isto functiona, suponha que uma variável do tipo double
ocupe 8 bytes de memória. Isso significa que um array de double com 5 elementos vai ocupar 40 bytes. Ao dividir 40 pelo tamanho de um dos elementos, que é 8, você obtém o número de elementos do array, que é 5 neste caso.
Fazer isso faz com que você possa adicionar ou remover elementos na inicialização do array sem se preocupar em atualizar o valor do tamanho do array, já que as operações com o sizeof
irão calcular o tamanho do array novamente.
Só lembre-se que isto é em tempo de compilação, ou seja, é preciso recompilar o programa para alterar os elementos com os quais o array é inicializado. Só assim sizeof
retornará o valor atualizado do tamanho do array.