Nomes de Variáveis
As variáveis no C podem ter qualquer nome se duas condições forem satisfeitas: o nome deve começar com uma letra ou sublinhado (_) e os caracteres subsequentes devem ser letras, números ou sublinhado (_). Há apenas mais duas restrições: o nome de uma variável não pode ser igual a uma palavra reservada, nem igual ao nome de uma função declarada pelo programador, ou pelas bibliotecas do C. Variáveis de até 32 caracteres são aceitas. Mais uma coisa: é bom sempre lembrar que o C é "case sensitive" e portanto deve-se prestar atenção às maiúsculas e minúsculas.
Dicas quanto aos nomes de variáveis...
- É uma prática tradicional do C, usar letras minúsculas para nomes de variáveis e maiúsculas para nomes de constantes. Isto facilita na hora da leitura do código;
- Quando se escreve código usando nomes de variáveis em português, evita-se possíveis conflitos com nomes de rotinas encontrados nas diversas bibliotecas, que são em sua maioria absoluta, palavras em inglês.
Os Tipos do C
O C tem 5 tipos básicos: char, int, float, void, double. Destes não vimos ainda os dois últimos: O double é o ponto flutuante duplo e pode ser visto como um ponto flutuante com muito mais precisão. O void é o tipo vazio, ou um "tipo sem tipo". A aplicação deste "tipo" será vista posteriormente.
Para cada um dos tipos de variáveis existem os modificadores de tipo. Os modificadores de tipo do C são quatro: signed, unsigned, long e short. Ao float não se pode aplicar nenhum e ao double pode-se aplicar apenas o long. Os quatro modificadores podem ser aplicados a inteiros. A intenção é que short e long devam prover tamanhos diferentes de inteiros onde isto for prático. Inteiros menores (short) ou maiores (long). int normalmente terá o tamanho natural para uma determinada máquina. Assim, numa máquina de 16 bits, int provavelmente terá 16 bits. Numa máquina de 32, int deverá ter 32 bits. Na verdade, cada compilador é livre para escolher tamanhos adequados para o seu próprio hardware, com a única restrição de que shorts ints e ints devem ocupar pelo menos 16 bits, longs ints pelo menos 32 bits, e short int não pode ser maior que int, que não pode ser maior que long int. O modificador unsigned serve para especificar variáveis sem sinal. Um unsigned int será um inteiro que assumirá apenas valores positivos. A seguir estão listados os tipos de dados permitidos e seu valores máximos e mínimos em um compilador típico para um hardware de 16 bits. Também nesta tabela está especificado o formato que deve ser utilizado para ler os tipos de dados com a função scanf():
Tipo | Num de bits | Formato para leitura com scanf | Intervalo | |
Inicio | Fim | |||
char | 8 | %c | -128 | 127 |
unsigned char | 8 | %c | 0 | 255 |
signed char | 8 | %c | -128 | 127 |
int | 16 | %i | -32.768 | 32.767 |
unsigned int | 16 | %u | 0 | 65.535 |
signed int | 16 | %i | -32.768 | 32.767 |
short int | 16 | %hi | -32.768 | 32.767 |
unsigned short int | 16 | %hu | 0 | 65.535 |
signed short int | 16 | %hi | -32.768 | 32.767 |
long int | 32 | %li | -2.147.483.648 | 2.147.483.647 |
signed long int | 32 | %li | -2.147.483.648 | 2.147.483.647 |
unsigned long int | 32 | %lu | 0 | 4.294.967.295 |
float | 32 | %f | 3,4E-38 | 3.4E+38 |
double | 64 | %lf | 1,7E-308 | 1,7E+308 |
long double | 80 | %Lf | 3,4E-4932 | 3,4E+4932 |
O tipo long double é o tipo de ponto flutuante com maior precisão. É importante observar que os intervalos de ponto flutuante, na tabela acima, estão indicados em faixa de expoente, mas os números podem assumir valores tanto positivos quanto negativos.
Declaração e Inicialização de Variáveis
As variáveis no C devem ser declaradas antes de serem usadas. A forma geral da declaração de variáveis é:
tipo_da_variável lista_de_variáveis;
As variáveis da lista de variáveis terão todas o mesmo tipo e deverão ser separadas por vírgula. Como o tipo default do C é o int, quando vamos declarar variáveis int com algum dos modificadores de tipo, basta colocar o nome do modificador de tipo. Assim um long basta para declarar um long int.
Por exemplo, as declarações
char ch, letra;
long count;
float pi;
declaram duas variáveis do tipo char (ch e letra), uma variavel long int (count) e um float pi.
Há três lugares nos quais podemos declarar variáveis. O primeiro é fora de todas as funções do programa. Estas variáveis são chamadas variáveis globais e podem ser usadas a partir de qualquer lugar no programa. Pode-se dizer que, como elas estão fora de todas as funções, todas as funções as vêem. O segundo lugar no qual se pode declarar variáveis é no início de um bloco de código. Estas variáveis são chamadas locais e só têm validade dentro do bloco no qual são declaradas, isto é, só a função à qual ela pertence sabe da existência desta variável, dentro do bloco no qual foram declaradas. O terceiro lugar onde se pode declarar variáveis é na lista de parâmetros de uma função. Mais uma vez, apesar de estas variáveis receberem valores externos, estas variáveis são conhecidas apenas pela função onde são declaradas.
Veja o programa abaixo:
#include
int contador;
int func1(int j) {
/* aqui viria o código da funcao
...
*/
}
int main()
{
char condicao;
int i;
for (i=0; i<100; i=i+1)
{ /* Bloco do for */
float f2;
/* etc ...
...
*/
func1(i);
}
/* etc ... */
return(0);
}
A variável contador é uma variável global, e é acessível de qualquer parte do programa. As variáveis condição e i, só existem dentro de main(), isto é são variáveis locais de main. A variável float f2 é um exemplo de uma variável de bloco, isto é, ela somente é conhecida dentro do bloco do for, pertencente à função main. A variável inteira j é um exemplo de declaração na lista de parâmetros de uma função (a função func1).
As regras que regem onde uma variável é válida chamam-se regras de escopo da variável. Há mais dois detalhes que devem ser ressaltados. Duas variáveis globais não podem ter o mesmo nome. O mesmo vale para duas variáveis locais de uma mesma função. Já duas variáveis locais, de funções diferentes, podem ter o mesmo nome sem perigo algum de conflito.
Podemos inicializar variáveis no momento de sua declaração. Para fazer isto podemos usar a forma geral
tipo_da_variável nome_da_variável = constante;
Isto é importante pois quando o C cria uma variável ele não a inicializa. Isto significa que até que um primeiro valor seja atribuído à nova variável ela tem um valor indefinido e que não pode ser utilizado para nada. Nunca presuma que uma variável declarada vale zero ou qualquer outro valor. Exemplos de inicialização são dados abaixo :
char ch='D';
int count=0;
float pi=3.141;
Ressalte-se novamente que, em C, uma variável tem que ser declarada no início de um bloco de código. Assim, o programa a seguir não é válido em C (embora seja válido em C++).
int main()
{
int i;
int j;
j = 10;
int k = 20; /* Esta declaracao de variável não é válida,
pois não está sendo feita no início do bloco */
return(0);
}
AUTO AVALIAÇÃO
Veja como você está:
Escreva um programa que declare uma variável inteira global e atribua o valor 10 a ela. Declare outras 5 variáveis inteiras locais ao programa principal e atribua os valores 20, 30, ..., 60 a elas. Declare 6 variáveis caracteres e atribua a elas as letras c, o, e, l, h, a . Finalmente, o programa deverá imprimir, usando todas as variáveis declaradas:
As variáveis inteiras contem os números: 10,20,30,40,50,60
O animal contido nas variáveis caracteres e' a coelha
Constantes são valores que são mantidos fixos pelo compilador. Já usamos constantes neste curso. São consideradas constantes, por exemplo, os números e caracteres como 45.65 ou 'n', etc...
Abaixo vemos as constantes relativas aos tipos básicos do C:
Tipo de Dado | Exemplos de Constantes |
char | 'b' '\n' '\0' |
int | 2 32000 -130 |
long int | 100000 -467 |
short int | 100 -30 |
unsigned int | 50000 35678 |
float | 0.0 23.7 -12.3e-10 |
double | 12546354334.0 -0.0000034236556 |
- Constantes hexadecimais e octais
Muitas vezes precisamos inserir constantes hexadecimais (base dezesseis) ou octais (base oito) no nosso programa. O C permite que se faça isto. As constantes hexadecimais começam com 0x. As constantes octais começam em 0.
Alguns exemplos:
Constante | Tipo |
0xEF | Constante Hexadecimal (8 bits) |
0x12A4 | Constante Hexadecimal (16 bits) |
03212 | Constante Octal (12 bits) |
034215432 | Constante Octal (24 bits) |
Nunca escreva portanto 013 achando que o C vai compilar isto como se fosse 13. Na linguagem C 013 é diferente de 13!
- Constantes strings
Já mostramos como o C trata strings. Vamos agora alertar para o fato de que uma string "Joao" é na realidade uma constante string. Isto implica, por exemplo, no fato de que 't' é diferente de "t", pois 't' é um char enquanto que "t" é uma constante string com dois chars onde o primeiro é 't' e o segundo é '\0'.
O C utiliza, para nos facilitar a tarefa de programar, vários códigos chamados códigos de barra invertida. Estes são caracteres que podem ser usados como qualquer outro. Uma lista com alguns dos códigos de barra invertida é dada a seguir:
Código | Significado |
\b | Retrocesso ("back") |
\f | Alimentação de formulário ("form feed") |
\n | Nova linha ("new line") |
\t | Tabulação horizontal ("tab") |
\" | Aspas |
\' | Apóstrofo |
\0 | Nulo (0 em decimal) |
\\ | Barra invertida |
\v | Tabulação vertical |
\a | Sinal sonoro ("beep") |
\N | Constante octal (N é o valor da constante) |
\xN | Constante hexadecimal (N é o valor da constante) |
Operadores Aritméticos e de Atribuição
Os operadores aritméticos são usados para desenvolver operações matemáticas. A seguir apresentamos a lista dos operadores aritméticos do C:
Operador | Ação |
+ | Soma (inteira e ponto flutuante) |
- | Subtração ou Troca de sinal (inteira e ponto flutuante) |
* | Multiplicação (inteira e ponto flutuante) |
/ | Divisão (inteira e ponto flutuante) |
% | Resto de divisão (de inteiros) |
++ | Incremento (inteiro e ponto flutuante) |
-- | Decremento (inteiro e ponto flutuante) |
O C possui operadores unários e binários. Os unários agem sobre uma variável apenas, modificando ou não o seu valor, e retornam o valor final da variável. Os binários usam duas variáveis e retornam um terceiro valor, sem alterar as variáveis originais. A soma é um operador binário pois pega duas variáveis, soma seus valores, sem alterar as variáveis, e retorna esta soma. Outros operadores binários são os operadores - (subtração), *, / e %. O operador - como troca de sinal é um operador unário que não altera a variável sobre a qual é aplicado, pois ele retorna o valor da variável multiplicado por -1.
O operador / (divisão) quando aplicado a variáveis inteiras, nos fornece o resultado da divisão inteira; quando aplicado a variáveis em ponto flutuante nos fornece o resultado da divisão "real". O operador % fornece o resto da divisão de dois inteiros.
Assim seja o seguinte trecho de código:
int a = 17, b = 3;int x, y;
float z = 17. , z1, z2;
x = a / b;
y = a % b;
z1 = z / b;
z2 = a/b;
ao final da execução destas linhas, os valores calculados seriam x = 5, y = 2, z1 = 5.666666 e z2 = 5.0 . Note que, na linha correspondente a z2, primeiramente é feita uma divisão inteira (pois os dois operandos são inteiros). Somente após efetuada a divisão é que o resultado é atribuído a uma variável float.
Os operadores de incremento e decremento são unários que alteram a variável sobre a qual estão aplicados. O que eles fazem é incrementar ou decrementar, a variável sobre a qual estão aplicados, de 1. Então
x++;
x--;são equivalentes a
x=x+1;
x=x-1;
Estes operadores podem ser pré-fixados ou pós- fixados. A diferença é que quando são pré-fixados eles incrementam e retornam o valor da variável já incrementada. Quando são pós-fixados eles retornam o valor da variável sem o incremento e depois incrementam a variável. Então, em
x=23;y=x++;
teremos, no final, y=23 e x=24. Em
x=23;
y=++x;
teremos, no final, y=24 e x=24. Uma curiosidade: a linguagem de programação C++ tem este nome pois ela seria um "incremento" da linguagem C padrão. A linguagem C++ é igual à linguagem C só que com extensões que permitem a programação orientada a objeto, o que é um recurso extra.
O operador de atribuição do C é o =. O que ele faz é pegar o valor à direita e atribuir à variável da esquerda. Além disto ele retorna o valor que ele atribuiu. Isto faz com que as seguintes expressões sejam válidas:
x=y=z=1.5; /* Expressao 1 */
if (k=w) ... /* Expressão 2 */
A expressão 1 é válida, pois quando fazemos z=1.5 ela retorna 1.5, que é passado adiante, fazendo y = 1.5 e posteriormente x = 1.5. A expressão 2 será verdadeira se w for diferente de zero, pois este será o valor retornado por k=w. Pense bem antes de usar a expressão dois, pois ela pode gerar erros de interpretação. Você não está comparando k e w. Você está atribuindo o valor de w a k e usando este valor para tomar a decisão.
AUTO AVALIAÇÃO
Veja como você está:
Diga o resultado das variáveis x, y e z depois da seguinte seqüência de operações:
int x,y,z;
x=y=10;
z=++x;
x=-x;
y++;
x=x+y-(z--);
Operadores Relacionais e Lógicos
Os operadores relacionais do C realizam comparações entre variáveis.
São eles:
Operador | Ação |
> | Maior do que |
>= | Maior ou igual a |
< | Menor do que |
<= | Menor ou igual a |
== | Igual a |
!= | Diferente de |
Os operadores relacionais retornam verdadeiro (1) ou falso (0). Para verificar o funcionamento dos operadores relacionais, execute o programa abaixo:
/* Este programa ilustra o funcionamento dos operadores relacionais. */
#include
int main()
{
/*int i, j;
printf("\nEntre com dois números inteiros: ");
scanf("%d%d", &i, &j);
printf("\n%d == %d é %d\n", i, j, i==j);
printf("\n%d != %d é %d\n", i, j, i!=j);
printf("\n%d <= %d é %d\n", i, j, i<=j);
printf("\n%d >= %d é %d\n", i, j, i>=j);
printf("\n%d < %d é %d\n", i, j, i
printf("\n%d > %d é %d\n", i, j, i>j);
return(0);*/
}
Você pode notar que o resultado dos operadores relacionais é sempre igual a 0 (falso) ou 1 (verdadeiro).
Para fazer operações com valores lógicos (verdadeiro e falso) temos os operadores lógicos:
Operador | Ação |
&& | AND (E) |
|| | OR (OU) |
! | NOT (NÃO) |
Usando os operadores relacionais e lógicos podemos realizar uma grande gama de testes. A tabela-verdade destes operadores é dada a seguir:
p falso falso verdadeiro verdadeiro | q falso verdadeiro falso verdadeiro | p AND q falso falso falso verdadeiro | p OR q falso verdadeiro verdadeiro verdadeiro |
O programa a seguir ilustra o funcionamento dos operadores lógicos. Compile-o e faça testes com vários valores para i e j:
#include
int main()
{
int i, j;
printf("informe dois números(cada um sendo 0 ou 1): ");
scanf("%d%d", &i, &j);
printf("%d AND %d é %d\n", i, j, i && j);
printf("%d OR %d é %d\n", i, j, i || j);
printf("NOT %d é %d\n", i, !i);
}
Exemplo: No trecho de programa abaixo a operação j++ será executada, pois o resultado da expressão lógica é verdadeiro:
int i = 5, j =7;if ( (i > 3) && ( j <= 7) && ( i != j) ) j++;
V AND V AND V = V
Mais um exemplo. O programa abaixo, imprime na tela somente os números pares entre 1 e 100, apesar da variação de i ocorrer de 1 em 1:
/* Imprime os números pares entre 1 e 100. */
#include
int main()
{
int i;
for(i=1; i<=100; i++)
if(!(i%2)) printf("%d ",i);/* o operador de resto dará falso (zero) */
} /* quando usada c/ número par. Esse resultado*/
/* é invertido pelo ! */
- Operadores Lógicos Bit a Bit
O C permite que se faça operações lógicas "bit-a- bit" em números. Ou seja, neste caso, o número é representado por sua forma binária e as operações são feitas em cada bit dele. Imagine um número inteiro de 16 bits, a variável i, armazenando o valor 2. A representação binária de i, será: 0000000000000010 (quinze zeros e um único 1 na segunda posição da direita para a esquerda). Poderemos fazer operações em cada um dos bits deste número. Por exemplo, se fizermos a negação do número (operação binária NOT, ou operador binário ~ em C), isto é, ~i, o número se transformará em 1111111111111101. As operações binárias ajudam programadores que queiram trabalhar com o computador em "baixo nível". As operações lógicas bit a bit só podem ser usadas nos tipos char, int e long int. Os operadores são:
Operador | Ação |
& | AND |
| | OR |
^ | XOR (OR exclusivo) |
~ | NOT |
>> | Deslocamento de bits à direita |
<< | Deslocamento de bits à esquerda |
Os operadores &, |, ^ e ~ são as operações lógicas bit a bit. A forma geral dos operadores de deslocamento é:
valor>>número_de_deslocamentos
valor<
O número_de_deslocamentos indica o quanto cada bit irá ser deslocado. Por exemplo, para a variável i anterior, armazenando o número 2:
i << 3; fará com que i agora tenha a representação binária: 0000000000010000, isto é, o valor armazenado em i passa a ser igual a 16.
AUTO AVALIAÇÃO
Veja como você está:
Diga se as seguintes expressões serão verdadeiras ou falsas:
-> ((10>5)||(5>10))
-> (!(5==6)&&(5!=6)&&((2>1)||(5<=4)))
Expressões
Expressões são combinações de variáveis, constantes e operadores. Quando montamos expressões temos que levar em consideração a ordem com que os operadores são executados, conforme a tabela de precedências da linguagem C.
Exemplos de expressões:
Anos=Dias/365.25; i = i+3;
c= a*b + d/e;
c= a*(b+d)/e;
- Conversão de tipos em expressões
Quando o C avalia expressões onde temos variáveis de tipos diferentes o compilador verifica se as conversões são possíveis. Se não são, ele não compilará o programa, dando uma mensagem de erro. Se as conversões forem possíveis ele as faz, seguindo as regras abaixo:
- Todos os chars e short ints são convertidos para ints. Todos os floats são convertidos para doubles.
- Para pares de operandos de tipos diferentes: se um deles é long double o outro é convertido para long double; se um deles é double o outro é convertido para double; se um é long o outro é convertido para long; se um é unsigned o outro é convertido para unsigned.
- Expressões que Podem ser Abreviadas
O C admite as seguintes equivalências, que podem ser usadas para simplificar expressões ou para facilitar o entendimento de um programa:
Expressão Original | Expressão Equivalente |
x=x+k; | x+=k; |
x=x-k; | x-=k; |
x=x*k; | x*=k; |
x=x/k; | x/=k; |
x=x>>k; | x>>=k; |
x=x< | x<<=k; |
x=x&k; | x&=k; |
etc... |
O operador , determina uma lista de expressões que devem ser executadas seqüencialmente. Em síntese, a vírgula diz ao compilador: execute as duas expressões separadas pela vírgula, em seqüência. O valor retornado por uma expressão com o operador , é sempre dado pela expressão mais à direita. No exemplo abaixo:
x=(y=2,y+3);
o valor 2 vai ser atribuído a y, se somará 3 a y e o retorno (5) será atribuído à variável x . Pode-se encadear quantos operadores , forem necessários.
O exemplo a seguir mostra um outro uso para o operador , dentro de um for:
#include
int main()
{
int x, y;
for(x=0 , y=0 ; x+y < 100 ; ++x , y++)/* Duas variáveis de
controle: x e y . Foi atribuído o valor zero a cada uma delas na
inicialização
do for e ambas são incrementadas na parte de incremento do for */
printf("\n%d ", x+y); /* o programa imprimirá
os números pares de 2 a 98 */
}
- Tabela de Precedências do C
Esta é a tabela de precedência dos operadores em C. Alguns (poucos) operadores ainda não foram estudados, e serão apresentados em aulas posteriores.
Maior precedência | () [] -> |
! ~ ++ -- . -(unário) (cast) *(unário) &(unário) sizeof | |
* / % | |
+ - | |
<< >> | |
<<= >>= | |
== != | |
& | |
^ | |
| | |
&& | |
|| | |
? | |
= += -= *= /= | |
Menor precedência | , |
Uma dica aos iniciantes: Você não precisa saber toda a tabela de precedências de cor. É útil que você conheça as principais relações, mas é aconselhável que ao escrever o seu código, você tente isolar as expressões com parênteses, para tornar o seu programa mais legível.
Modeladores (Casts)
Um modelador é aplicado a uma expressão. Ele força a mesma a ser de um tipo especificado. Sua forma geral é:
(tipo)expressão
Um exemplo:
#include
#include
int main ()
{
int num;
float f;
num=10;
f=(float)num/7; /* Uso do modelador . Força a transformação de num em um float */
printf ("%f",f);
return(0);
}
Se não tivéssemos usado o modelador no exemplo acima o C faria uma divisão inteira entre 10 e 7. O resultado seria 1 (um) e este seria depois convertido para float mas continuaria a ser 1.0. Com o modelador temos o resultado correto.
AUTO AVALIAÇÃO
Veja como você está:
Compile o exemplo acima sem usar o modelador, e verifique os resultados. Compile-o novamente usando o modelador e compare a saída com os resultados anteriores.