Elementos da Liguagem
Elementos
Identificadores
- Sequências de letras, underscore, ou dígitos
- Primeiro caracter é letra ou underscore
- Identificadores são case-sensitive
int i, I; /* Duas variáveis diferentes */
- Frequentemente nomes nas bibliotecas começam com underscore para minimizar possíveis conflitos
- Por convenção usa-se o nome de
variaveis
em minúsculas eCONSTANTES
em maiúsculas - Nomes reservados:
if
,else
,int
,float
, etc.
Tipos de Dados
-
char
,int
,float
,double
short int
,int
,long int
-
signed/unsigned
char
,short
,int
,long
-
unsigned
obedece aritmética módulo 2^n (n = número bits) -
signed char
entre -128 e 127 -
Tamanho
char
= 1 byte (= 8 bits) -
Tamanho-típico
int
= 4 bytes (=32 bits) -
Tamanho
short
<= Tamanhoint
<= Tamanholong
-
Tamanho
float
<= Tamanhodouble
<= Tamanholong double
-
Obter o tamanho de um tipo:
sizeof()
Formatos de Leitura & Escrita
char
:%c
int
:%d
ou%i
(base decimal)int
:%x
(base hexadecimal)short int
:%hd
long int
:%ld
unsigned short int
:%hu
unsigned int
:%u
unsigned long int
:%lu
float
edouble
:%f
Conversão de Tipos
- Argumentos de operadores de diferentes tipos provocam transformação de tipos dos argumentos
- Algumas conversões automáticas: de representações
"estreitas" para representações mais "largas".
- Exemplo:
conversão de
int
parafloat
emf + i
- Exemplo:
conversão de
char
é um inteiro pequeno e podem-se fazer operações aritméticas com caracteres
int atoi(char s[]) /*Função que recebe uma stirng de digitos todos juntos
e devolve o inteiro correspondente*/
{
int i, n;
n = 0;
for (i = 0; s[i] >= '0' && s[i] <= '9'; i++)
n = 10 * n + (s[i] - '0');
return n;
}
Conversão Forçada de Tipos
-
Conversão forçada de tipos: utilização de operador
cast
-
Valor
expressão
convertido para tipotipo
como se tratasse de atribuição -
Exemplo:
int i = (int) 2.34;
-
Conversão de
float
paraint
:truncagem
-
Conversão de
double
parafloat
:truncagem
ouarredondamento
-
Nas chamadas a funções, não é necessário recorrer a uma conversão forçada de tipos
ex:double sqrt (double x);
root2 = sqrt(2);
é equivalente aroot2 = sqrt(2.0);
Constantes - Tipos Enumerados
- Tipo enumerado definido por sequência de constantes
enum resposta { NAO, SIM };
- Tipo
resposta
tem duas constantes:NAO
eSIM
- Constantes de tipo enumerado têm valor inteiro (
int
): a primeira constante vale0
, a segunda vale1
, etc - Tipo
resposta
:NAO
vale 0 eSIM
vale 1 - Pode-se especificar valores para as constantes ou não
enum meses { JAN=1, FEV=2, MAR, ABR, MAI, JUN, JUL, AGO, SET, OUT, NOV, DEZ };
- Permite criar uma abstracção dos valores quando se programa usando apenas os nomes do tipo enumerado
#include <stdio.h>
enum meses
{
JAN = 1,
FEV, /* = 2 */
MAR, /* = 3 */
ABR, /* ... */
MAI,
JUN,
JUL,
AGO,
SET,
OUT,
NOV,
DEZ /* = 12 */
};
int main()
{
enum meses mes;
mes = FEV;
mes++;
if (mes == MAR)
puts("Estamos em Março");
/*Escreve a string*/
return 0;
}
Declarações de Variáveis
Precedem utilização e especificam tipo e lista das variáveis
/*Sequência de declarações*/
int superior, inferior, passo;
char c, linha[1000];
/*Alternativa*/
int superior;
int inferior;
int passo;
char c;
char linha[1000];
-
Inicialização de variáveis externas (
globais
) e estáticas:
<tipo> <variável> = <expressão constante>;
-
Variáveis globais são declaradas fora das funções
-
Variáveis estáticas podem ser locais a uma função, mas mantêm o valor entre chamadas à função
Caso de omissão: valor 0
Em C só as variáveis globais e estáticas são inicializadas automaticamente a 0, se o utilizador não fornecer nenhuma inicialização explícita
-
Exemplo:
int pi = 3.14159;
-
Inicialização de variáveis automáticas
locais
:<tipo> <variável> = <expressão>;
- Variáveis automáticas são reinicializadas sempre que a função é invocada
-
Caso de omissão em variáveis locais:
valor indefinido
Exemplo: int i, j = f(5);
int global; /*global = 0*/
int contador()
{
static int i = 1; /*Só inicializa i a 1 */
/*Depois de inicializada esta instrução é ignorada */
return i++;
}
int main()
{
int a = global + contador();
int b = contador();
int c = contador();
printf("a = %d, b = %d, c = %d\n", a, b, c);
return 0; /* a = 1, b = 2, c = 3 */
}
const
pode anteceder qualquer declaração- Significa que valor não vai mudar
- Se tentar modificar o valor, o compilador detecta como sendo um erro
- Compilador pode tirar partido e fazer optimizações
const double e = 2.71828182845905;
const char msg[] = "bem vindo ao C";
int strlen(const char[]);
Inicialização de Variáveis
- Posso fazer a mesma coisa com vectores inteiros
int numbers[] = {1, 44, 12, 567};
- até com vectores de vectores (strings, neste caso)
char codes[][3] ={"AA", "AB", "BA","BB"};
[3] = 2 char's + '\0' - Para imprimir o "AB" basta escrever
printf("%s",codes[1]);
int numbers[10] = {1, 44, 12, 567};
Os restantes são inicializados a 0.
Operações
Operadores e Precedências
- Operadores Aritméticos :
+ - * / %
- Operadores Relacionais :
> >= < <= == !=
- Operadores Lógicos :
! && | |
Precedências:
!
>>> Aritméticos >>> Relacionais >>> Lógicos
Valores de Verdade
- Verdadeiro = 1
- Falso = 0
!0 = 1
!x = 0
Uma estrutura permite definir estruturas de dados sofisticadas, as quais possibilitam a agregação de diferentes tipos de declarações.
Operadores Bit a Bit
Em C é possível efectuar operações sobre a representação binária
Manipular bits em inteiros (char, short, int, long):
&
AND
bit a bit|
OR
bit a bitˆ
XOR
(OR exclusivo) bit a bit<<
shift left>>
shift right
Ambos os shifts adicionam 0.
int x = 1, y = 2;
int z = x & y;
int w = x && y;
printf("z = %d w = %d \n", z, w);
/*z = 0 , w = 1 */
Expressões Condicionais
- Expressão condicional: expressão cujo valor depende de
uma outra expressão
<expr1> ? <expr2> : <expr3>
- Se
<expr1>
for verdadeiro, valor da expressão é<expr2>
- Se
<expr1>
for falso, valor da expressão é<expr3>
int maior(int a, int b)
{
if (a > b)
return a;
else
return b;
}
int maior(int a, int b)
{
return (a > b ? a : b);
}
Slides: