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 e CONSTANTES 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)

  • Tamanhoshort<= Tamanhoint <= Tamanholong

  • Tamanhofloat<= 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 e double : %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 para float em f + i
  • 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 tipo tipo como se tratasse de atribuição

  • Exemplo: int i = (int) 2.34;

  • Conversão de float para int : truncagem

  • Conversão de double para float: truncagem ou arredondamento

  • 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 a root2 = sqrt(2.0);

Constantes - Tipos Enumerados

  • Tipo enumerado definido por sequência de constantes
    enum resposta { NAO, SIM };
  • Tipo resposta tem duas constantes: NAO e SIM
  • Constantes de tipo enumerado têm valor inteiro (int): a primeira constante vale 0, a segunda vale 1, etc
  • Tipo resposta: NAO vale 0 e SIM 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: