Linguagem C Brian W. Kernighan, Dennis Ritchie (K&R) Slides adaptados, inspirados, muitos copiados dos slides do professor Pedro Pereira Centro de Cálculo Instituto Superior de Engenharia de Lisboa João Pedro Patriarca ([email protected]) C versus Java • C – – – – – – – Dennis Ritchie: 196?-197? Programação de sistemas Desenhado para estar “perto” do hardware Acesso directo à memória (eficiência tempo/espaço) Permite portabilidade entre várias plataformas de hardware Portabilidade ao nível do código fonte Linguagem procedimental • Java – James Gosling: 199? – Sintaxe semelhante a C – Suporte de OOP com mais mecanismos automáticos mas menos liberdade nos paradigmas suportados CCISEL, 2010 Programação em Sistemas Computacionais 2 Perigos e (des)vantagens face a Java • Gestão de memória feita explicitamente – Java tem gestão automática com garbage collection • Iniciação explícita – Java inicia os campos e detecta utilização sem iniciação • Detecção de erros explícita – Java gera excepção (referência a null, indexação fora dos limites, …) • Mais linhas de código para a mesma funcionalidade • Fácil cometer erros não detectados pelo compilador • Não existe portabilidade de código já compilado – As bibliotecas não são portáveis • Não existe uma interface gráfica standard e portável CCISEL, 2010 Programação em Sistemas Computacionais 3 Exemplo em C #include <stdio.h> int main() { int nextChar; /* char readed */ int count = 0; /* words counter */ int inWord = 0; /* current state */ while (( nextChar = getchar() ) != EOF) { if (nextChar == '\n'|| nextChar == ' ') inWord = 0; else if (! inWord) { inWord = 1; ++count; } } printf("Words=%d\n",count); return 0; } CCISEL, 2010 Programação em Sistemas Computacionais words.c 4 Expressões, Instruções e Blocos bib: K&R, cap. 2 • Uma expressão produz um valor 1<<5 32 8%3 2 Se a tinha 5 (a+1)*2 12 ++a*2 12 depois fica com: 5 6 a=3 3 3 a==5 1 5 • Instrução: expressão terminada por „;‟ a=3; a=(a+1)*2; • Bloco: sequência de instruções entre chavetas – Corpo de funções – Instruções do if, while, for, … { x++; a=x*4; } #include <stdio.h> int main() { int nextChar; /* char readed */ int count = 0; /* words counter */ int inWord = 0; /* current state */ while (( nextChar = getchar() ) != EOF) { if (nextChar == '\n'|| nextChar == ' ') inWord = 0; else if (! inWord) { inWord = 1; ++count; } } printf("Words=%d\n",count); return 0; } Programação em Sistemas Computacionais 5 { x++; a=x*4; } CCISEL, 2010 Instruções de controlo e valores lógicos bib: K&R, cap. 3 • As instruções de controlo de fluxo do programa têm sintaxe e semântica equivalentes à linguagem Java • Na linguagem C não existe o tipo boolean – Uma expressão de controlo é verdadeira se o resultado for diferente de 0 int x = 10; while (x) { putchar(„.‟); --x; } – O resultado da avaliação das operações relacionais é 1 ou 0 b = x==x; CCISEL, 2010 1 b = 10<5; Programação em Sistemas Computacionais 0 6 Identificadores, Tipos e Constantes bib: K&R, cap. 2 • Identificadores – As mesmas regras de Java: … • Tipos básicos (char, int, float, double) – Modificadores de dimensão (short, long) aplicáveis a int – Modificadores de sinal (signed, unsigned) aplicáveis a int e char • Constantes – – – – int: 23 023 0x23 23L 23U double ou float: 23.5 23.5F 23. 23.F 12.3e-4 12.3e10F char: „K‟ „\n‟ „\t‟ „\‟‟ „\\‟ „\0‟ „\113‟ „\x48‟ string: “abc” “aspas=\”” “linha\n” #include <stdio.h> int main() { int nextChar; /* char readed */ int count = 0; /* words counter */ alerta (bell) int inWord = 0; /* current state */ while (( nextChar = getchar() ) != EOF) { Tabulador if (nextChar == '\n'|| nextChar == ' ') inWord = 0; Backspace else if (! inWord) { Carácter backslash inWord = 1; ++count; } } printf("Words=%d\n",count); return 0; } Programação em Sistemas Computacionais 7 • Sequências de escape: – – – – CCISEL, 2010 \a \t \b \\ Variáveis/Declarações bib: K&R, cap. 2 char c; int i = 10; • Nome – Zona de memória associada a um nome • Tipo – Significado e dimensão dos valores armazenados • Âmbito (scope) – Onde é vista a variável • Bloco de função, Argumento de função, Global, outros blocos… • Tempo de vida – Desde a reserva de memória à libertação #include <stdio.h> int main() { int nextChar; /* char readed */ int count = 0; /* words counter */ int inWord = 0; /* current state */ while (( nextChar = getchar() ) != EOF) { if (nextChar == '\n'|| nextChar == ' ') inWord = 0; else if (! inWord) { inWord = 1; ++count; } } printf("Words=%d\n",count); return 0; } Programação em Sistemas Computacionais 8 • Automático (sujeito ao bloco) • Estático (sujeito ao programa) • Qualificador const const double PI=3.1415926535; CCISEL, 2010 Tipo char bib: K&R, cap. 2 Tipo Utilização Dimensão signed char unsigned char char Valores -128..+127 Valores muito pequenos Código de um carácter int main(void) { signed char sc= 0; unsigned char uc= 0; char c = 0; 8 bits (1 byte) 0..255 ??? primitiveTypes.c char cA='A', ca; for(ca=cA-'A'+'a' ; cA<='Z' ; ++cA, ++ca) printf("%c-%d %c-%d\n",cA,cA,ca,ca); --sc; --uc; --c; printf("%d, %d, %c, %d\n",sc,uc,c,c); A-65 a-97 B-66 b-98 C-67 c-99 D-68 d-100 ... X-88 x-120 Y-89 y-121 Z-90 z-122 -1, 255, , -1 return 0; } CCISEL, 2010 Programação em Sistemas Computacionais 9 Tipo int bib: K&R, cap. 2 Tipo signed int ou int unsigned int long int ou long unsigned long short int ou short unsigned short Utilização Dimensão típica (32 bits) Valores inteiros 32 bits (4 bytes) Valores grandes Valores pequenos Valores -231..+231-1 0..232-1 (232=4.294.967.296) 31 31 32 ou 64 bits -2 ..+2 -1 (4 ou 8 bytes) 0..232-1 16 bits (2 bytes) -215..+215-1 0..216-1 (216=65.536) Standard só garante: sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long) unsigned int ui=~0u; primitiveTypes.c unsigned long ul=~0u; unsigned short us=~0u; printf(“max unsigned\n\tint=%u\n” “\tlong=%u\n\tshort=%u\n” “signed int=~0=%d”,ui,ul,us,ui); CCISEL, 2010 Programação em Sistemas Computacionais max unsigned int=4294967295 long=4294967295 short=65535 signed int=~0=-1 10 Tipo float e double bib: K&R, cap. 2 Tipo Utilização Dimensão Expoente Mantissa (norma IEEE 754) (bits) (bits) Valores reais pequenos 32 bits (4 bytes) Valores reais double grandes 64 bits (8 bytes) float 8 11 Valores 23 ±1.40×10-45.. ±3.40×10+38 52 ±4.94×10-324.. ±1.76×10+308 • • • • v = ±m × 2e m = 1.M, e = E-127 M é a mantissa, valendo cada bit: 2-1 + 2-2 + 2-3 +…+ 2-22 + 2-23 E é o expoente, valendo cada bit: 27 + 26 + 25 +…+ 20 • • M=2-2=0.25m=1.25 E=011111002=124e=-3 v=+1.25×2-3=0.15625 Existem representações especiais para: zero, infinito e indeterminado CCISEL, 2010 Programação em Sistemas Computacionais 11 Conversão de tipos bib: K&R, cap. 2 • Conversão implícita – Verificada em tempo de compilação – Promoção • char int float double • short int int long int – Em expressões quando os operandos são de tipos diferentes • Conversão para o tipo mais abrangente • Conversão explícita (cast) – Para realizar despromoções • Podem gerar código CCISEL, 2010 int small = 10L; long large = small; ??? any; any = large + small; small = (int) large; short int val = -1; small = (int) val; Programação em Sistemas Computacionais 12 Operadores bib: K&R, cap. 2 • Aritméticos: • Precedência e Associatividade – Quatro operadores entre inteiros e reais: +, -, * e / – Resto de divisão inteira: % – Operadores unários: + e – – Incremento e decremento (prefixo e sufixo): ++ e –– • • • • Relacionais: >, >=, <, <=, == e != Lógicos: &&, || e o unário ! Bit a bit: &, |, ^, <<, >> e o unário ~ Afectação: = – Compostos: +=, -=, *=, /=, %=, &=, |=, ^=, <<= e >>= CCISEL, 2010 () ! & * + << < == & ^ | && || ?: = , Programação em Sistemas Computacionais [] -> . ~ ++ -- + - * (type) sizeof / % >> <= > >= != += -= … 13 Função printf() bib: K&R, cap. 7 {.2} pc.c #include <stdio.h> void printChar(int c) { printf(“Char „%c‟ code=%d hex=0x%x\n”,c,c,c); } int main(void) { printChar(‟A‟); printChar(‟H‟); return 0; Char „A‟ code=65 hex=0x41 } Char „H‟ code=72 hex=0x48 %c %d %x %X %o %u %f Carácter cujo código é o valor Valor inteiro em decimal Valor inteiro em hexadecimal Valor inteiro em octal Valor inteiro sem sinal Valor real CCISEL, 2010 \% Programação em Sistemas Computacionais sequência de escape 14 Compilar, Ligar e executar (Linux/GNU) $ gcc –Wall –g –c words.c – Compila o ficheiro fonte words.c e gera o ficheiro words.o com o código compilado – Neste passo são detectados os erros de compilação • pre-processador; sintaxe; semânticos $ gcc words.o –o words – Liga words.o com a biblioteca standard e gera o ficheiro executável words – Neste passo são detectados erros de ligação • Símbolo não encontrado $ ./words < abc.txt – Executa o programa dando como entrada (input) o conteúdo do ficheiro abc.txt – Neste passo são detectados os erros de execução • O programa não cumpre o objectivo Debug CCISEL, 2010 $ insight words Programação em Sistemas Computacionais 15