Aula 5: Variáveis

Traduzido por Ana Paula Costa

Tipos de Variáveis

As variáveis armazenam valores e informação. Elas permitem que os programas efectuem cálculos e armazenem os resultados para utilização futura. Imaginemos uma variável como uma caixa que pode conter informação. Quando se deseja saber essa informação, abre-se a caixa e lê-se o valor. No final, volta-se a colocar a informação na caixa, onde fica até ser necessária novamente.

Para facilitar a identificação, e para evitar confusão, cada caixa tem que ter um nome, um identificador (ver aula 4). 

O tipo da caixa define o seu tamanho e o tipo de informação que se pode encontrar lá dentro. As variáveis podem ter muitos tamanhos e formas.

As variáveis podem armazenar números, nomes, textos, etc. Nas versões modernas de C existem muitos tipos básicos de variáveis. A implementação exacta dos tipos de variáveis depende do compilador. Para o compilador Borland C temos:
 

 grupo
 tipo de variável
 intervalo
 espaço ocupado em memória
II
 unsigned char 
0 .. 255
 8 bit = 1 byte
II
 char
 -128 .. 127
 8 bit = 1 byte
II
 int
 -32 768 .. 32 767
 16 bit = 2 bytes
II
 unsigned int
 0 .. 65 535
 16 bit = 2 bytes
II
 long
 -2 147 483 648 .. 2 147 483 647 
 32 bit = 4 bytes
II
 unsigned long
0 .. 4 294 967 295
 32 bit = 4 bytes
III
 float
 -3.4E-38 .. 3.4E38
 32 bit = 4 bytes
III
 double
 -1.7E-324 .. 1.7E308
 64 bit = 8 bytes
III
 long double
 -3.4E-4932 .. 1.1E4932
 80 bit = 10 bytes
IV
 char
 #0 .. #255 ASCII
 8 bit = 1 byte

Notas:


I Boolean é usado para armazenar e manipular informação do tipo verdadeiro- ou-falso ou sim/não. Como se viu na aula 3, isto representa um bit de informação. Em C este tipo de variável não existe. É emulada com inteiros, onde "falso" é igual a 0 e qualquer outro valor é igual a "verdadeiro".
 
 

II int, unsigned int, e long e char e unsigned char todos armazenam valores de números completos. Podem ser usados para coisas que podem ser contadas; número de pessoas numa sala, número de portas de um carro, número de telefonemas que alguém fez, ano lectivo, dia do mês, etc. Unsigned char e int apenas armazenam números positivos, enquanto int e long armazenam números positivos e negativos, até ao limite do valor máximo. O char ocupa o mínimo de memória, apenas 8 bits, mas o intervalo de valores que pode assumir é por isso muito limitado, apenas 256 valores diferentes. Se é necessário armazenar valores maiores, é preciso utilizar int. Se se desejar armazenar números ainda maiores e utilizar valores positivos e negativos utiliza-se long.
Nota: dado que um char tem 8 bits, pode armazenar 28 = 256 números diferentes: 0 .. 255 ou -128..127. Os mesmos cálculos podem ser feitos para as unidades de 16-bits int e unsigned int: 216 = 65536, números de 0 .. 65535 para unsigned int, e -32768 .. 32767 para int. Recordem os cálculos da aula 3.

III Float, double e long double são exemplos de variáveis que podem armazenar números de vírgula flutuante ("floating point numbers"), por exemplo 3.1415926535. São usados para coisas não contáveis, como o comprimento de um carro, o intervalo de tempo entre dois acontecimentos, a altura de um edifício, a raíz-quadrada de 3, etc. O tipo mais pequeno é float, que ocupa apenas 4 bytes, com o custo de se conseguir uma menor precisão nos cálculos. O melhor é long double, com 80 bits (10 bytes), os cálculos terão uma precisão muito elevada, mas demorarão mais tempo e acuparão mais espaço em memória. Um bom meio-termo é usar double.

IV O último tipo é usado para armazenar texto. Char é utilizado para um único caracter do código ASCII. Uma vez que char pode ser utilizado para armazenar informação do tipo integer, bem como caracteres ASCII, é preciso ter muito cuidado para não cometer erros.

Mais tarde iremos aprender como definir os nossos próprios tipos de variáveis, por agora vamos ver como se podem usar os tipos básicos em C.


Variáveis: Declaração!

Na maioria das linguagens compiladas modernas, todas as variáveis que se irão usar têm que ser declaradas primeiro. A isto chama-se declaração. Para ser mais preciso, declarar significa reservar espaço em memória e associar-lhe um nome, de tal modo que mais tarde se pode utilizar o nome em vez do endereço de memória quando se desejar recuperar a informação.
Em C declaram-se as variáveis escrevendo o nome da variável precedido pelo tipo da variável. Por exemplo
  int i;
O local de declaração de variáveis é no início da função (main), antes da primeira instrução. Por exemplo:

main()
{
  int i;
  float f;
  long li;

  instruction1;
  instruction2;
}
 
Sempre que o programa corre e uma instrução como int i; é encontrada, é reservado espaço em memória e o endereço desse espaço é relembrado para referência futura, quando for preciso armazenar informação nessa caixa ou recuperar o valor nela guardado. O espaço é libertado no fim da função (ou programa no caso de main).
Para os peritos: As variáveis são colocadas na stack e ficam lá até que o scope das variáveis expire.

Se se desejar definir várias variáveis do mesmo tipo, pode-se fazê-lo numa única linha com as variáveis separadas por vírgulas. Embora não seja proibitivo usar várias linhas para definir diferentes variáveis do mesmo tipo.

main()
{
  int i, j, k;
  float f;
  float g;
  int n;

  instruction1;
  instruction2;
}
Esquecer de declarar variáveis origina um erro de compilação.


Problemas com variáveis I: Mistura de tipos

É preciso ter sempre muito cuidado quando se realizam cálculos de diferentes tipos de valores. Considerando o código que se segue:

main()
{
  int i, j;
  float f;

  i = 1;
  j = 3;
  f = i/j;
  printf("%f", f);
}
Qual será o valor de f no final? Por outras palavras, qual será o resultado do programa?
NÃO 0.3333 como seria de esperar. Em vez disso, o valor de f será 0.0000. Isto deve-se ao facto do cálculo da divisão ser feita com valores inteiros, e 1 dividido por 3 na divisão inteira é 0, que é o valor atribuído a f.
Para evitar esta situação pode-se

  * forçar o tipo do valor nos cálculos. A isto chama-se "type casting". Por exemplo:
     f = (float) i/ (float) j;

  * Quando os cálculos são efectuados com constantes, pode-se forçar o tipo directamente no valor:
     f = 1.0 / 3.0;
   instead of
     f = 1 / 3;


Problemas com variáveis II: Overflow


Considerando o seguinte programa:

main()
{
  int i, j, k;

  i = 20000;
  j = 20000;
  k = i + j;
  printf("%d", k);
}
Mais uma vez, qual será o resultado do programa? Ingenuamente, podemos pensar que será 40000, mas k é do tipo int e os inteiros vão apenas até 32767. Que é feito com o resto? O que aconteçe é que a parte restante ("overflowing part") reentra no limite inferior do intervalo. Neste caso iremos obter -25536. Um overflow pode ocorrer quando se adicionam dois números com intervalo limitado. Um underflow pode acorrer quando se subtrai 2 números.
Isto é mais fácil de demonstrar com uma variável que ocupe apenas um byte (um byte tem 8 bits e um intervalo de 0 a 255 e é chamado unsigned char em C):
 
i
130 =
 10000010
j
130 =
 10000010
i+j 
(260)=
  100000100

O que acontece é que o 9.º bit da equação anterior é ignorado e o resultado será o valor binário 00000100 que é igual a 4 no sistema decimal. Assim, calculando usando um byte, 130 + 130 = 4.

O que pode ser feito para prevenir esta situação?


Problemas com variáveis III: Inicialização

Declarar uma variável não lhe atribui nenhum valor, apenas lhe reserva espaço em memória!
main()
{
  int day;

  printf("Today is day %d\n", day);
}
No programa de cima, o resultado poderá ser

Today is day 23741

Quando o computador é ligado, normalmente a memória é preenchida com zeros, mas passado algum tempo, depois de muitos programas terem usado a memória e deixado aí algum lixo, o conteúdo de um endereço de memória é imprevissível. Para garantir que se está a trabalhar com valores bem definidos é sempre preciso atribuir um valor a cada variável. Na próxima aula iremos aprender como fazer isso num programa utilizando instruções de atribuição. Por agora é suficiente disser o seguinte: "Nunca se deve assumir que o valor inicial das variáveis é 0".
Nota: Em muitas linguagens de programação é possível atribuir um valor a uma variável no momento da sua declaração. Para se fazer isso em C pode-se usar
  int day = 0;


printf

A instruçao printf é uma das instruções mais úteis em C e é utilizada para mostrar informação no écran: texto, números, valores de variáveis, etc. Qualquer programa tem uma instrução printf algures. Já se mostraram alguns exemplos da utilização de printf, mas até agora ainda não de discutiu o funcionamento desta função.
printf faz parte da biblioteca standard-input-output (stdio.h). O resultado é formatado, o que significa que se pode especificar exactamente como queremos que a informação surja no écran (quanto espaço deve ocupar no écran, quantos dígitos significativos devem ser mostrados para floats, etc.). O formato é sempre o primeiro argumento da função. O(s) argumento(s) seguinte(s) respeitam à informação a ser mostrada, separada por vírgulas.
  printf("%d", i);
irá mostrar o valor de uma variável do tip integer a que se chamou i
  3
para cada informação tem que se especificar o formato:
  printf("%d %d", i, j);
  3 5
Outros especificadores de formatos com interesse:
 
%d 
%i 
%u 
%x 
%f 

%e 
%c 
%s

inteiro com sinal 
inteiro com sinal 
inteiro sem sinal
hexadecimal
float (31.2000) 
por exemplo %10.3f mostra o float com 10 espaços no écran e 3 casas decimais 
float com notação científica (3.12E1) 
caracter ASCII 
string

De notar que também se pode escrever texto directamente no formato:
  printf("Hello%d World", i);
dará como resultado (quando i=3)
  Hello3 World
Existem caracteres especiais que se podem utilizar para controlar a posição do resultado no ecrán. Eles são escritos com \. O mais importante é:
 
\n  vai para o início da próxima linha

Por exemplo
  printf("Hello\n%d World", i);
dará como resultado (quando i=3)
  Hello
  3 World


Teste Rápido:

Para testar os conhecimentos sobre o que aprendeu nesta aula, prima aqui para fazer um teste on-line. De notar que este Não é o formato que será utilizado no teste final!


Peter Stallinga. Universidade do Algarve, 22 October 2002