A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Linguagem C Curso de Nivelamento LCG - 2004. AVISO Estas transparências contêm apenas o que eu me lembro da linguagem Ultimamente, minha memória tem falhado.

Apresentações semelhantes


Apresentação em tema: "Linguagem C Curso de Nivelamento LCG - 2004. AVISO Estas transparências contêm apenas o que eu me lembro da linguagem Ultimamente, minha memória tem falhado."— Transcrição da apresentação:

1 Linguagem C Curso de Nivelamento LCG

2 AVISO Estas transparências contêm apenas o que eu me lembro da linguagem Ultimamente, minha memória tem falhado bastante Detalhes devem ser procurados nos manuais

3 Linguagem C Proposta por Kernighan e Ritchie (1970) Linguagem para desenvolvimento de sistemas UNIX supostamente deveria ser todo escrito em C Permite construções pouco seguras Ponteiros podem ser usados para endereçar toda a memória Muito popular e usada até hoje Variantes mais atualizadas e +seguras foram sendo propostas ANSI C Objective C (NextStep) C++ C# (Microsoft.NET) 90% do software básico de hoje é escrito em C ou C++

4 Programa em C Organizado em unidades de compilação Cada unidade é um arquivo com extensão.c podendo conter diversas diretivas de inclusão de outros arquivos-fonte: #include #include foobar.h arquivo.h include Nome entre : include em diretórios- padrão Nome entre aspas: include no mesmo diretório que o arquivo.c

5 Programa em C Um programa simples tem apenas uma unidade Unidade principal é a que contém a função main

6 Declarações e Definições Arquivos-fonte contêm Declarações Informam nomes e tipos de variáveis e funções Diretivas para o pré-compilador #include #define #if / #ifdef Definição de funções Onde os comandos são efetivamente escritos Comentários /* Comentário */ // Também aceito em alguns compiladores (não é padrão)

7 Programa Exemplo #include char *titulo = "Programa Exemplo\n"; /* * Programa para imprimir argumentos dados */ int main (int argc, char * argv []) { int i; printf (titulo); printf ("Argumentos:\n"); for (i = 0; i < argc; ++i) { printf ("%d: %s\n", i, argv[i]); } return 0; } Diretiva de inclusão Declaração de variável global Função main (Programa principal) uso da função printf definida em stdio.h parâmetros da função main argc: número de args argv: array de strings Variável local função main retorna 0 para indicar sucesso

8 Pré-processador Processa as diretivas #... Compilador na verdade vê o programa fonte pré-processado Pré-processador não entende C, apenas processa textos #include inclui o arquivo indicado como se tivesse sido digitado naquela linha

9 #define Também chamado de macro #define nome texto sempre que nome for citado no programa, será substituído por texto Exemplo: #define X a, b, c f (X);... é equivalente a f (a, b, c);

10 #define É possível ter macros parametrizadas #define nome ( arg1,...argN ) texto texto contém os símbolos arg que são substituídos pelos valores passados quando do uso Exemplo: #define MAX(a,b) a > b ? a : b x = MAX(b,c);... é equivalente a x = b > c ? b : c;

11 #define Cuidado! substituição é literal: #define MAX(a,b) a > b ? a : b x = MAX(x & 2, 1);... é equivalente a x = x & 2 > 1 ? x & 2 : 1;... que é equivalente a x = (x & (2 > 1)) ? (x & 2) : 1; Nesses casos, é melhor usar parênteses #define MAX(a,b) ((a)>(b) ? (a) : (b))

12 Compilação condicional Expediente para obter variações do mesmo código adaptado a diversos ambientes Diretivas #if, #ifdef, #else, #endif Exemplo: #ifdef WIN... código que contorna bug do Windows #else... código normal #endif

13 Dados em C Tipos nativos int, float, double, char modificadores : unsigned, signed, long, short Ponteiros: tipo * Arrays: tipo [ tamanho ] Enumerações: enum { nomes } Estruturas: struct { campos } union { campos }

14 Declaração de variáveis em C ?qualif??alocação? tipo var ? = valor?; qualif volatile pode mudar inesperadamente (multithreading) const valor constante alocação extern definido em outra unidade de compilação static tempo de vida estático auto alocada na pilha de execução register alocada em registradores

15 Declaração de variáveis em C tipo é um nome de tipo nativo ou previamente declarado var é identificador *var var [tamanho] = valor inicialização da variável valor tem que ser uma expressão constante uma expressão constante é aquela que pode ser avaliada pelo compilador

16 Exemplos register int i, j, k; auto unsigned char a[10]; static double *p[10]; float **f; const double pi = ; extern unsigned long int param; struct { int s1; char c; } s; enum { pera, limao, maca } fruta;

17 Declaração de tipos typedef decl ; decl tem o mesmo formato de uma declaração de variáveis, mas sem qualificadores identificadores que aparecem em decl vão ser associados a nomes de tipos, e não variáveis nomes de tipos podem ser usados em declarações posteriormente Exemplo: typedef int * ponteiro; ponteiro p, *pp;

18 Arrays Coleção de valores do mesmo tipo alocados em seqüência na memória int a [10]; 10 variáveis inteiras referenciadas como a[0], a[1],... a[9] Arrays multidimensionais são alocados com os índices mais à esquerda variando mais rápido int b[2][2][2] = {5,2,3,9,1,2,3,4}; b[0][0][0]b[0][0][1]b[0][1][0]b[0][1][1]b[1][0][0]b[1][0][1]b[1][1][0]b[1][1][1] Endereços crescentes de memória

19 Inicialização de arrays Um array pode ser inicializado assim que declarado Lista de valores é posta entre chaves Para arrays multidimensionais, a inicialização é por linha Exemplo int i [10] = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 }; int m [3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };

20 Inicialização de arrays Arrays de caracteres podem ser inicializados com uma cadeia de caracteres entre aspas ( string ) É assumido um caractere nulo no fim da string Exemplo char s [10] = alo; É o mesmo que char s [10] = {a,l,o,\0}; Observe que posições não inicializadas têm valor indefinido

21 Ponteiros Variáveis que contêm o endereço de outra variável Recurso poderoso mas perigoso! int i = 5, *p = &i; i p 2126 Identificadores Endereços 5 i p Endereço de i

22 Ponteiros e Arrays Um ponteiro e um array muitas vezes se confundem uma vez que o nome de um array é interpretado como o endereço do primeiro elemento do array Por exemplo: int a [3] = {1,2,3}; int *p, *q; p = a; q = p; Após este código, a, p e q referem-se todos ao mesmo endereço

23 Ponteiros e Arrays De forma semelhante, ponteiros podem ser indexados como arrays: p [1] = 7; *(p+1) = 7; Entretanto, arrays e ponteiros não são a mesma coisa Um ponteiro ocupa uma palavra de memória e um array várias Um array não pode mudar de endereço Qual o significado de a = p ?

24 Estruturas Tipo agregado heterogêneo Conjunto de campos com nomes Imprescindível para construção de estruturas de dados mais complexas Base para o conceito de classe em C++

25 Estruturas Forma geral: struct ?nome? { decl;... decl; } var; onde nome é o nome da estrutura decl é uma declaração de campo (semelhante às declarações de variáveis; var é uma ou mais variáveis que se quer declarar podem ser simples, arrays ou ponteiros

26 Estruturas Exemplo: a declaração struct S { int a; char b, *s, n[10]; struct S * ptr; } v1, v2 [10], *q;... declara uma estrutura v1, um array de 10 estruturas v2 e um ponteiro para estrutura q

27 Estruturas Os campos da estrutura são acessados escrevendo o nome da variável e o nome do campo separados por um ponto: v1.a = 1; *v2[4].s = a; (*q).n[2] = b; Se p é um ponteiro para uma estrutura, pode-se substituir a construção (*p).campo por p->campo q->n[2] = b;

28 Uniões Semelhantes a struct, mas todos os campos ocupam a mesma área de memória Usar com muito cuidado! Sintaxe: trocar struct por union Exemplo: union { int a; double b; char c; } x; x.a = 10; /* Quanto vale x.b ??? */

29 Expressões Compostas de operandos, operadores e parênteses Operandos variáveis: a, b, c, *p, t[b], t[a+5] constantes: 1, 1L, 2.4, a, xxxxx chamadas de função: f(), g(2, 4)

30 Expressões Operadores Aritméticos: +, -, /,* Comparação: ==, !=, >, =, <= Lógicos: &&, ||, ! Bit a Bit: &, |, ~, ^ Condicional: expr ? expr : expr Referência e Dereferência: &, * Cast: ( tipo ) expr Parênteses: servem para alterar a ordem de precedência Precedência funciona quase sempre como se espera: a * b + c == d && *x = 1 Na dúvida: olhar o livro ou usar parênteses

31 Expressões com efeito colateral Ao avaliar a expressão, alguma variável pode mudar de valor. Por exemplo: a = b = 4 ; a recebe o valor da expressão b = 4 expressão vale 4, mas tem como efeito colateral atribuir 4 a b Chamar funções pode ter efeito colateral: Ex.: f(&a) pode alterar o valor de a (ou de qualquer variável global) Outros operadores com efeito colateral: Misturas de atribuição com operadores binários: +=, *=, /=, &=, |= etc Pré e Pós incremento/decremento: ++ e –– a = x++; a = x; x = x+1; a = ++x; x = x+1; a = x;

32 Funções Encapsulam os algoritmos Forma geral: tipo nomefunção ( arg,... arg ) { declaração ;... declaração ; comando ;... comando ; } tipo do valor de retorno Lista de parâmentros

33 Valor de retorno de Funções O tipo de retorno pode ser um tipo simples: int, double, char, etc; um ponteiro (endereço) Se a função é avaliada e não passa por nenhum comando return, então o valor retornado é indefinido Se a função não retorna valores, pode-se usar void como tipo de retorno Mesmo que uma função retorne um valor, este não necessariamente é usado por quem chama: i = g(5); g(9);

34 Argumentos de funções Lista de argumentos é semelhante à declaração de variáveis Parâmetros são passados por valor, à exceção de array s e struct s Um parâmetro passado por valor é equivalente a uma variável local inicializada com o valor passado Para alterar uma variável passada como argumento, usa-se ponteiros

35 Passagem de Parâmetros int j = 4; void f (int i) { i = 5; } int main () { f (j); printf (%d\n, j); } Resultado: 4

36 Passagem de Parâmetros int j[1] = { 4 }; void f (int i[]) { i[0] = 5; } int main () { f (j); printf (%d\n, j[0]); } Resultado: 5

37 Passagem de Parâmetros int j = 4; void f (int *i) { *i = 5; } int main () { f (&j); printf (%d\n, j); } Resultado: 5

38 if Comando condicional fundamental Formato1: if ( expr ) comando1 Se expr avaliar como qualquer valor diferente de 0, comando1 é executado. Formato2: if ( expr ) comando1 else comando2 Se expr avaliar como qualquer valor diferente de 0, comando1 é executado, senão, comando2 é executado

39 Comando composto Vários comandos sintaticamente equivalentes a um só Formato: { decl ;... decl ; comando ;.... comando ; } OBS.: Todo comando é terminado por um ponto-e-vírgula Comandos compostos não precisam de ponto-e- vírgula Ex.: if (a == b) { c = d; printf (OK); } else { c = b; printf (Não OK); }

40 switch Permite selecionar um entre vários caminhos Formato: switch { expr } { case val : comando ;... comando ;... case val : comando ;... comando ; default : comando ;... comando ; } Avalia expr, procura o val igual e começa a executar os comandos subseqüentes Se não encontrar, executa os comandos após a cláusula default (se existir) OBS.: o switch não pula os demais case s. Para encerrar o case, usar o comando break

41 break Interrompe o comando composto atual e retoma a execução no próximo comando Muito usado em switches e laços de repetição Ex.: switch (i) { case 1: case 2: i = 3; case 3: case 4: k = 4; break; case 5: k = 9; break; default: k = 10; }

42 while... do e do... while while ( expr ) comando enquanto expr é diferente de 0, comando é repetido pode não executar comando nenhuma vez do comando while ( expr ) repete comando enquanto expr é diferente de 0 sempre executa comando pelo menos uma vez

43 for for ( expr1 ; expr2 ; expr3 ) comando equivale a expr1 ; while ( expr2 ) { comando ; expr3 ; } 90% das vezes, alguma coisa como for (i = 0; i < n; i++) { a [i] =...; }

44 bibliotecas fornecem o restante da funcionalidade da linguagem entrada e saída controle de processos e multiprogramação comunicação c/ sistema operacional matemática gráficos e multimídia etc usar uma biblioteca requer: inclusão dos headers da biblioteca no programa cliente link-edição da biblioteca com o executável

45 Entrada e Saída (I/O) Duas bibliotecas padrão I/O de baixo nível Usa chamadas diretas do Sistema Operacional entrada e saída sem buferização #include I/O de alto nível Usa I/O de baixo nível entrada e saída buferizadas suporta formatação de dados binários em texto e vice-versa: scanf, printf #include

46 Entrada e Saída c/ stdio Dados são lidos/escritos em arquivos Estado de um arquivo é guardado em memória por um tipo struct chamado FILE RFunções que lidam com arquivos têm parâmetros do tipo FILE* Existem 3 arquivos de entrada/e saída default: stdin arquivo de entrada default stdout arquivo de saída default stderr arquivo de saída de mensagens de erro normalmente associados ao terminal (ver o tópico redirecionamento na documentação do seu Sistema Operacional)

47 printf saída formatada uso: printf ( formato, expr1,... exprN ); igual a fprintf ( stdout, formato,...); expr são os valores que se quer imprimir formato é uma string comum, mas intercalada com especificadores de formato

48 printf Alguns especificadores de formato: %c escreve um caractere %d escreve um inteiro em decimal %x escreve um %ld escreve um inteiro longo em decimal %g escreve um float ou double %s escreve uma cadeia (string) Exemplo: int i = 10; char c = a; double d = ; printf (i vale %d, c vale %c e d vale %g, i, c, d);

49 printf Opcionalmente, especificadores podem incluir modificadores entre o % e a letra. Ex.: %10d escreve usando 10 caracteres (preenchido com brancos) %010d escreve usando 10 caracteres (preenchido com zeros) %10.3g escreve em 10 caracteres, mantendo 3 casas decmais

50 scanf análogo do printf para leitura uso: scanf ( formato, addr1,... addr2 ); retorna o número de valores lidos addr são endereços de variáveis Exemplo: int i; char c; float f; if (scanf (%d %c %f, &i, &c, &f) != 3) fprintf (stderr, falha ao converter algum dado\n); Importante: como sempre ao manipular endereços, é preciso cuidado redobrado: scanf (%d %c %g, &i, &c, &f); scanf espera um double e não um float!

51 Alocação de Memória variáveis estáticas ( static ) alocadas de uma vez só quando da carga programa variáveis automáticas ( auto ) alocadas quando o fluxo de execução entra num bloco e desalocadas quando sai Para ter estruturas de dados de tamanho variável é necessário alocar memória dinâmicamente

52 malloc #include void * malloc ( nbytes ) retorna um ponteiro para uma área livre de nbytes bytes área não é inicializada (pode conter lixo) para saber quantos bytes são necessários para guardar um dado, usar a função sizeof ( tipo ) Exemplo: queremos alocar dinâmicamente um array de n doubles double *a = (double*) malloc(sizeof(double)*n);

53 free desfaz o trabalho do malloc retorna a memória alocada para o sistema uso: free (p); onde p é um ponteiro alocado por malloc, calloc ou realloc

54 Programa exemplo: listas #include typedef struct NoStruct { int val; struct NoStruct * prox; } NoLista, * Lista;

55 Programa exemplo: listas void push (Lista* pLista, int n) { Lista tmp = (Lista) malloc (sizeof (NoLista)); assert (pLista != NULL); tmp->val = n; tmp->prox = *pLista; *pLista = tmp; } int top (Lista lista) { assert (lista != NULL); return lista->val; }

56 Programa exemplo: listas void pop (Lista* pLista) { Lista tmp; assert (pLista != NULL); assert (*pLista != NULL); tmp = *pLista; *pLista = tmp->prox; free (tmp); } void print (Lista lista) { if (lista == NULL) { printf ("\n"); } else { printf ("%d ", top(lista)); print (lista->prox); }

57 Programa exemplo: listas int main () { Lista l = NULL; push (&l, 1); push (&l, 2); push (&l, 3); print (l); pop (&l->prox); print (l); return 0; }


Carregar ppt "Linguagem C Curso de Nivelamento LCG - 2004. AVISO Estas transparências contêm apenas o que eu me lembro da linguagem Ultimamente, minha memória tem falhado."

Apresentações semelhantes


Anúncios Google