Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Programação de computadores em C, Manuais, Projetos, Pesquisas de Engenharia Informática

programação em linguagem c

Tipologia: Manuais, Projetos, Pesquisas

2017

Compartilhado em 18/04/2017

maria-luiza-de-amorim-8
maria-luiza-de-amorim-8 🇧🇷

5

(1)

3 documentos

1 / 123

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Programação de Computadores
em
C
Primeira edição
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b
pf4c
pf4d
pf4e
pf4f
pf50
pf51
pf52
pf53
pf54
pf55
pf56
pf57
pf58
pf59
pf5a
pf5b
pf5c
pf5d
pf5e
pf5f
pf60
pf61
pf62
pf63
pf64

Pré-visualização parcial do texto

Baixe Programação de computadores em C e outras Manuais, Projetos, Pesquisas em PDF para Engenharia Informática, somente na Docsity!

Programação de Computadores

em C

Primeira edição

Sumário

  • 1 Computadores e Programas Prefácio vii
    • 1.1 Computadores e Algoritmos
    • 1.2 Algoritmo e Programa
    • 1.3 Funcionamento e Organização de Computadores
    • 1.4 Exercícios Resolvidos
    • 1.5 Exercícios
    • 1.6 Notas Bibliográcas
  • 2 O Paradigma Imperativo de Programação
    • 2.1 Variável e Atribuição
    • 2.2 Operadores
    • 2.3 Expressões
    • 2.4 Programando em C
    • 2.5 Exercícios
    • 2.6 Notas Bibliográcas
  • 3 Programando em C
    • 3.1 Exercícios Resolvidos
    • 3.2 Exercícios
  • 4 Escolha condicional
    • 4.1 Exercícios
  • 5 Recursão e Iteração
    • 5.1 Repetição
    • 5.2 Multiplicação e Exponenciação
    • 5.3 Fatorial
    • 5.4 Obtendo Valores com Processos Iterativos
      • 5.4.1 Não-terminação
    • 5.5 Correção e Entendimento de Programas
      • 5.5.1 Denições Recursivas
      • 5.5.2 Comandos de Repetição
      • 5.5.3 Semântica Axiomática
      • 5.5.4 Exemplos
    • 5.6 Exercícios Resolvidos
    • 5.7 Exercícios
  • 6 Valores Compostos: Parte I
    • 6.1 Arranjos
      • 6.1.1 Declaração e Criação de Arranjos
      • 6.1.2 Arranjos criados dinamicamente
      • 6.1.3 Exemplo de Uso de Arranjo Criado Dinamicamente
      • 6.1.4 Operações Comuns em Arranjos
      • 6.1.5 Arranjos de arranjos
      • 6.1.6 Inicialização de Arranjos vi SUMÁRIO
      • 6.1.7 Exercícios Resolvidos
    • 6.2 Exercícios
    • 6.3 Ponteiros
      • 6.3.1 Operações de soma e subtração de valores inteiros a ponteiros
      • 6.3.2 Ponteiros e arranjos
    • 6.4 Cadeias de caracteres
      • 6.4.1 Conversão de cadeia de caracteres para valor numérico
      • 6.4.2 Conversão para cadeia de caracteres
      • 6.4.3 Passando valores para a função main
      • 6.4.4 Exercícios Resolvidos
      • 6.4.5 Exercícios
    • 6.5 Registros
      • 6.5.1 Declarações de tipos com typedef
      • 6.5.2 Ponteiros para registros
      • 6.5.3 Estruturas de dados encadeadas
    • 6.6 Exercícios Resolvidos
    • 6.7 Exercícios
    • 6.8 Notas Bibliográcas
  • 7 Exercícios
    • 7.1 ENCOTEL
    • 7.2 PAPRIMAS
    • 7.3 ENERGIA
    • 7.4 CIRCUITO
    • 7.5 POLEPOS
  • A Anexo: Por que a linguagem C
  • B Tipos básicos em C
    • B.1 Números
      • B.1.1 Consequências de uma representação nita
    • B.2 Caracteres
  • C Programas e Bibliotecas

viii Prefácio

  • http://publications.gbdirect.co.uk/c_book/: Página com a versão gratuita da segunda edição do livro The C Book , de Mike Banahan, Declan Brady e Mark Doran, publicado pela Addison Wesley em 1991.
  • http://www.cyberdiem.com/vin/learn.html: Learn C/C++ today, de V. Carpenter. Uma coleção de referências e tutoriais sobre as linguagens C e C++ disponíveis na Internet.
  • http://c-faq.com/index.html: Perguntas frequentes sobre a linguagem C, e suas respostas (em inglês).
  • http://cm.bell-labs.com/cm/cs/who/dmr/chist.html: "The Development of the C Lan- guage", Dennis M. Ritchie (Janeiro de 1993).
  • http://www.livinginternet.com/i/iw_unix_c.htm: "History of the C Programming Lan- guage", Stewart, Bill (Janeiro de 2000).
  • http://www.cs.ucr.edu/ nxiao/cs10/errors.htm: "10 Common Programming Mistakes in C".

Livros adicionais sobre a linguagem C incluem:

  • A linguagem de programação padrão ANSI C. B. Kernighan & D.C. Ritchie. Editora Campus,
  • C - completo e total. H. Schildt. Editora McGraw-Hill, 1990.a
  • C: A Reference Manual , Samuel P. Harbison & Guy L. Steele, quinta edição, Prentice Hall,
  • C Programming: A Modern Approach, K.N. King, Norton, 2008.

E por último, não perca: http://www.youtube.com/watch?v=XHosLhPEN3k

2 Computadores e Programas

Figura 1.1: Organização básica de um computador

fundamental das primeiras pesquisas teóricas em computação, as quais lançaram as bases para a ciência da computação e para a construção dos primeiros computadores.^1 Como construir algoritmos para a solução de problemas e como expressar tais algoritmos de modo adequado usando uma linguagem de programação constituem os temas centrais deste livro. Entretanto, faremos agora um pequeno parêntese para estudar brevemente as bases da organização e o funcionamento de um sistema de computação. Esse conhecimento nos permitirá entender como o computador executa os nossos programas.

1.3 Funcionamento e Organização de Computadores

A atual tecnologia de construção de computadores é baseada em dispositivos eletrônicos que são capazes de distinguir, com precisão, entre dois estados diferentes de um sinal elétrico, caracterizados pelos símbolos 0 e 1. Devido a essa característica, dados e operações são representados, em um computador, em uma linguagem que tem apenas esses dois símbolos, isto é, uma linguagem binária. Cada um desses símbolos é comumente chamado de bit.^2 Apesar do extraordinário avanço da atual tecnologia de construção de computadores, todo computador moderno mantém uma organização básica semelhante. Essa organização é mostrada na Figura 1.1 e seus componentes principais são descritos brevemente a seguir. O processador , também chamado de unidade central de processamento (do inglês CPU  Central Processing Unit), é o componente do computador que executa as instruções de um programa, expresso em uma linguagem que ele pode entender. Durante a execução de um programa, o processador lê a instrução corrente, executa a operação especicada nessa instrução e determina qual é a próxima instrução do programa que deve ser executada. Isso se repete até a execução de uma instrução que indica o término do programa. Muitas dessas instruções precisam de um lugar de onde tirar os operandos e onde armazenar temporariamente os resultados. Esse lugar é chamado de registrador, e podemos vê-lo como um conjunto de caixinhas etiquetadas onde guardamos dados (sequencias de bits que representam um número, um caracter, ou outro valor), um de cada vez. Outro componente do computador é a memória principal , em geral chamada simplesmente de memória, ou RAM (do inglês Random Access Memory). A memória é usada para armazenar os programas a serem executados pelo computador e os dados manipulados por esses programas. Essa característica de utilizar um único dispositivo de memória para armazenar tanto programas quanto dados, peculiar a todos os computadores modernos, é distintiva da chamada arquitetura de von Neumann, assim denominada em homenagem ao pesquisador alemão que originalmente publicou essa arquitetura, em 1946. A memória do computador consiste em uma seqüência nita de unidades de armazenamento de dados, cada qual identicada pelo seu endereço, isto é, por um número inteiro não-negativo que (^1) Veja as Notas Bibliográcas incluídas no nal deste capítulo. (^2) do inglês binary digit.

1.3 Funcionamento e Organização de Computadores 3

corresponde à sua posição nessa seqüência. Cada unidade de armazenamento de dados da memória é comumente chamada de uma palavra. Uma palavra de memória usualmente é composta de um pequeno número (em geral, 4 ou 8) de bytes  cada byte armazena uma seqüência de 8 bits. O outro grupo de componentes do computador é constituído pelos seus dispositivos de entrada e saída, também chamados de dispositivos periféricos (ou apenas de periféricos). Os periféricos são usados para a comunicação de dados entre o computador e o mundo externo. O teclado e o mouse são exemplos de dispositivos de entrada. A tela, ou monitor, e a impressora são exemplos de dispositivos de saída. Alguns dispositivos, como discos e pendrives, constituem dispositivos tanto de entrada quanto de saída de dados. A linguagem constituída pelas instruções que podem ser diretamente executadas pelo compu- tador, representadas na forma de seqüências de bits, é chamada de linguagem de máquina.

Linguagem de máquina

A linguagem de máquina de um computador consiste das instruções que seu processador pode entender. Elas são instruções para comandar a execução de operações básicas, tais como somar dois números ou comparar se dois números são iguais, instruções para transferência de dados entre a memória e os registradores do processador, ou entre a memória e os dispositivos de entrada e saída, e instruções para controlar o uxo de execução das instruções de um programa. Já que o que o processador entende são sequencias de bits, um programa escrito em linguagem de máquina deve estar escrito em esse formato. Vejamos um exemplo. Vamos escrever um programa para calcular o fatorial de um número. Lembremos da matemática que o fatorial de um número é o resultado da multiplicação sucessiva da sequência de inteiros de 1 até o número em questão. O nosso programa pode executar então:

fact ← num fact ← fact * (num - 1) fact ← fact * (num - 2) ... fact ← fact * 1 (Repare que agora em fact está o resultado nal!)

Nesse exemplo, vamos calcular o fatorial de 6. Para isto precisamos conhecer as instruções da má- quina na qual nosso programa será executado (o chamado de conjunto de instruções, ou instructions set), vamos supor que nosso processador entende no mínimo as seguintes instruções:

Operação Código COPIAR em registro um valor inteiro 0000 SUBSTRAIR do valor armazenado em um registro o inteiro especicado 0001 MULTIPLICAR o valor armazenado em um registro com o valor armazenado 0010 em outro e guardar o resultado no primeiro registro DESVIAR a execução da instrução seguinte 0011 se o valor resultante for maior do que zero IMPRIMIR o valor armazenado em um registro 0100

Assumamos que a nossa máquina tem no mínimo dois registros R1 e R2 em cujas etiquetas aparece 00 e 01 respectivamente. O nosso programa irá:

  • Copiar (Carregar) no registrador R1 o valor numérico 1;
  • Copiar (Carregar) no registrador R2 o valor numérico 6;
  • Multiplicar o valor armazenado no registrador R1 pelo valor no registrador R2 e armazená-lo no registrador R1;
  • Decrementar o valor armazenado no registrador R2;
  • Desviar para a instrução de multiplicação armazenada em um certo endereço da memória se o valor do registrador R2 for maior do que zero;

1.3 Funcionamento e Organização de Computadores 5

Linguagem de alto nível

Para facilitar a tarefa de programação, e torná-la mais produtiva, foram então desenvolvidas novas linguagens de programação. Essas novas linguagens foram chamadas linguagens de alto nível , por oferecer um conjunto muito mais rico de operações e construções sintáticas adequadas para expressar, de maneira mais natural, algoritmos usados na solução de problemas. Linguagens de máquina e linguagens de montagem são chamadas, em contraposição, linguagens de baixo nível.

Compilação

Para que um programa escrito em uma linguagem de alto nível possa ser executado pelo compu- tador, ele precisa ser primeiro traduzido para um programa equivalente em linguagem de máquina. Esse processo de tradução é chamado de compilação e o programa que faz essa tradução, de compi- lador. Um compilador é, portanto, simplesmente um programa tradutor, de programas escritos em uma determinada linguagem, chamada de linguagem fonte, para programas em outra linguagem, chamada de linguagem objeto. Os programas fornecidos como entrada e obtidos como saída de um compilador são também comumente chamados, respectivamente, de programa fonte (ou código fonte) e programa objeto (ou código objeto). Um compilador analisa o texto do programa fonte, para determinar se ele está sintaticamente correto, isto é, em conformidade com as regras da gramática da linguagem, e, em caso armativo, gera um código objeto equivalente. Caso o programa fonte contenha algum erro, o compilador então emite mensagens que auxiliam o programador na identicação e correção dos erros existentes.

Interpretação

Outro processo para execução de um programa em linguagem de alto nível, em vez da com- pilação desse programa seguida pela execução do código objeto correspondente, é a interpretação do programa fonte diretamente. Um interpretador é, como o nome indica, um programa que in- terpreta diretamente as frases do programa fonte, isto é, simula a execução dos comandos desse programa sobre um conjunto de dados, também fornecidos como entrada para o interpretador. A interpretação de programas escritos em uma determinada linguagem dene uma máquina virtual, na qual é realizada a execução de instruções dessa linguagem. A interpretação de um programa em linguagem de alto nível pode ser centenas de vezes mais lenta do que a execução do código objeto gerado para esse programa pelo compilador. A razão disso é que o processo de interpretação envolve simultaneamente a análise e simulação da execução de cada instrução do programa, ao passo que essa análise é feita previamente, durante a compilação, no segundo caso. Apesar de ser menos eciente, o uso de interpretadores muitas vezes é útil, principalmente devido ao fato de que, em geral, é mais fácil desenvolver um interpretador do que um compilador para uma determinada linguagem. Você provavelmente já ouviu falar alguma vez da linguagem Java. Um sistema (ambiente) de programação e execução de programas em Java é baseado em uma combinação dos processos de compilação e interpretação: um compilador Java gera um código de mais baixo nível, chamado de bytecodes, que é então interpretado. Um interpretador de bytecodes interpreta instruções da cha- mada Máquina Virtual Java (Em inglês JVM  Java Virtual Machine) Esse esquema usado no ambiente de programação Java não apenas contribuiu para facilitar a implementação da linguagem em grande número de computadores diferentes, mas constitui uma característica essencial no de- senvolvimento de aplicações voltadas para a Internet, pois possibilita que um programa compilado em um determinado computador possa ser transferido através da rede e executado em qualquer outro computador que disponha de um interpretador de bytecodes. Outras linguagens interpreta- das muito conhecidas são Python e Lua. Lua é uma linguagem de programação brasileira muito utilisada na programação de jogos que forma parte do Ginga, o padrão brasileiro de televisão digital.

Ambientes de Programação

Além de compiladores e interpretadores, um ambiente de programação de uma determinada linguagem de alto nível oferece, em geral, um conjunto de bibliotecas de componentes ou módulos de programas, usados comumente no desenvolvimento de programas para diversas aplicações. Além

6 Computadores e Programas

disso, ambientes de programação incluem outras ferramentas para uso no desenvolvimento de programas, como editores de texto e depuradores de programas. Um editor é um programa usado para criar um arquivo de dados e modicar ou armazenar dados nesse arquivo. O tipo mais simples de editor é um editor de texto, que permite editar (i.e. criar ou modicar) qualquer documento textual (um texto signicando uma seqüência de caracteres, separados linha por linha). Alguns editores usam caracteres especiais, chamados de caracteres de controle, para facilitar a visualização do texto editado, por exemplo colocando em destaque (em negrito ou com uma cor diferente) palavras-chave da linguagem. Um depurador é um programa que oferece funções especícas para acompanhamento da exe- cução de um programa, com o objetivo de auxiliar o programador na detecção e identicação da origem de erros que possam existir em um programa. Em um ambiente de programação convencional, editores, compiladores, interpretadores e depu- radores são programas independentes. Em um ambiente integrado de programação, ao contrário, as tarefas de edição, compilação, interpretação e depuração são oferecidas como opções disponíveis em um mesmo programa. A execução de programas em um computador é iniciada e controlada por um programa deno- minado sistema operacional. O sistema operacional controla a operação em conjunto dos diversos componentes do computador  processador, memória e dispositivos de entrada e saída  assim como a execução simultânea de diversos programas pelo computador. A execução do núcleo do sistema operacional é iniciada no momento em que o computador é ligado, quando esse núcleo é transferido do disco para a memória do computador, permanecendo residente na memória enquanto o computador estiver ligado. O núcleo do sistema operacional provê uma interface adequada entre a máquina e os demais programas do sistema operacional que, por sua vez, oferecem uma interface adequada entre os diversos componentes do computador e os usuários e seus programas, em um ambiente de programação.

1.4 Exercícios Resolvidos

  1. Mencionamos que os números são representados no computador usando a notação arábica, no sistema de numeração de base 2, ou sistema de numeração binário. Este exercício aborda a representação de números usando essa notação e a conversão entre as representações de números nos sistemas de numeração binário e decimal. A notação hindu-arábica, que usamos para escrever números em nosso sistema de numeração decimal, teria sido originada na Índia, no terceiro século a.C., sendo mais tarde levada para Bagdá, no oitavo século d.C. É interessante observar que o símbolo que representa o número zero só apareceu em um estágio posterior do desenvolvimento dessa notação, no século nove d.C. O nome notação arábica, mais comumente usado, se deve ao fato de que essa notação foi divulgada pela primeira vez por um matemático árabe, chamado al-Khuarizmi  daí o nome algarismo, dado aos símbolos que usamos atualmente para a representação de números no nosso sistema de numeração. A característica fundamental da notação hindu-arábica, que torna mais fácil representar nú- meros grandes e realizar operações sobre números, é o fato de ela ser uma notação posicional. No nosso sistema de numeração, de base 10, a posição de cada algarismo determina as potên- cias de 10 pelas quais devem ser multiplicados os números denotados por esses algarismos, para obter o número representado. Por exemplo: 496 = 4 × 102 + 9 × 101 + 6 × 100

Essa notação pode ser usada, de modo geral, para representação de números em um sistema de numeração de base b qualquer, onde b é um número inteiro positivo, com base no fato de que qualquer número inteiro não-negativo p pode ser univocamente representado na forma

p =

∑^ n

i=

di × bi

onde cada di, para i = 0,... , n, é um símbolo que representa um número de 0 a b − 1.

8 Computadores e Programas

Tabela 1.1: As operações lógicas não, ê, ou e ou exclusivo

Operação Resultado não ¬V F ¬F V

Operação Resultado (ê) (ou) (ou exclusivo) op = ∧ op = ∨ op = ⊕ V op V V V F V op F F V V F op V F V V F op F F F F

Figura 1.3: Circuito do meio-somador

Para entender como portas lógicas podem ser usadas para implementar a soma de números inteiros positivos em um computador, considere primeiramente a soma de dois números n e m, representados na base binária, cada qual com apenas 1 bit, ilustrada a seguir:

ou

n m vai um r 1 1 1 0 1 0 0 1 0 1 0 1 0 0 0 0

Ao comparar a tabela acima com as operações lógicas denidas na Tabela 1.1, é fácil perceber que a operação lógica ou exclusivo fornece o bit r do numeral que representa o resultado da soma n + m: o bit r é igual a 1 se n ou m for igual a 1 , mas não ambos, e é igual a 0 , caso contrário. O bit vai um desse numeral é obtido pela operação lógica ê: o bit vai um é igual a 1 quando n e m são iguais a 1 , e é igual a 0 em caso contrário. O resultado da soma n + m pode ser, portanto, representado pelo par (n ∧ m, n ⊕ m), em que o primeiro componente é o bit vai um e o segundo é o bit r do resultado. Note que m ⊕ n = (m ∨ n) ∧ ¬(m ∧ n). Com base nessas observações, ca fácil construir um circuito para somar dois números binários n e m, cada qual representado com apenas 1 bit. Esse circuito, chamado de meio-somador , é apresentado na Figura 1.3. Símbolos usuais são empregados, nessa gura, para representar as portas lógicas que implementam as operações ê, ou e não. O meio-somador pode ser usado para construir um circuito que implementa a soma de três números binários n, m e p, cada qual representado com apenas 1 bit, usando o fato de que a operação de adição é associativa: n + m + p = (n + m) + p. Sendo n + m = (v 1 , r 1 ) e r 1 + p = (v 2 , r), temos que n + m + p = (v 1 ∨ v 2 , r), uma vez que v 1 e v 2 não podem ser ambos iguais a 1. O circuito lógico que implementa a soma n + m + p, chamado de somador completo, pode ser construído como mostra a Figura 1.4. Podemos agora facilmente construir o chamado somador paralelo, para somar números intei- ros, representados no sistema de numeração binário, com qualquer número xo de bits.

1.4 Exercícios Resolvidos 9

Figura 1.4: Circuito do somador completo

Figura 1.5: Circuito do somador paralelo

A Figura 1.5 ilustra um circuito somador paralelo para somar números binários n e m, cada qual representado com 3 bits, ABC e DEF, respectivamente.

  1. Sabemos que um computador é capaz de operar com números inteiros, positivos ou negativos. Como números inteiros negativos são representados no computador? Para maior facilidade de armazenamento e de operação, todo número é representado, em um computador, por uma seqüência de bits de tamanho xo. No caso de números inteiros, esse tamanho é igual ao número de bits que podem ser armazenados na palavra do computador. Em grande parte dos computadores modernos, esse tamanho é de 32 bits ou, em computadores ainda mais modernos, de 64 bits. Para representar tanto números inteiros não-negativos quanto negativos, um determinado bit dessa seqüência poderia ser usado para indicar o sinal do número  essa abordagem é chamada de sinal-magnitude. A abordagem de sinal-magnitude não é muito adequada, pois existem nesse caso duas possí- veis representações para o zero e as operações de somar números não é tão simples quanto no caso da representação em complemento de dois, usada em todos os computadores modernos. A característica fundamental dessa representação é a de que a operação de somar 1 ao maior inteiro positivo fornece o menor inteiro negativo. Desse modo existe apenas uma representa- ção para o zero e pode-se realizar operações aritméticas de modo bastante simples. Ilustramos, na Tabela 1.2, a representação de números na notação de complemento de 2 em um computador com uma palavra de apenas 4 bits. Note que existem 2 n^ combinações distintas em uma palavra de n bits, e portanto é possível representar 2 n^ números inteiros, que na representação de complemento de dois compreendem os inteiros na faixa de − 2 (n−1) a 2 (n−1)^ − 1. O complemento de 2 de um número inteiro positivo p, 0 < p ≤ 2 n−^1 , com relação a n bits, denotado por cn 2 (p), é denido como sendo a representação na base binária, com n bits, do

1.6 Notas Bibliográcas 11

(a) 19 (b) 458

  1. Determine a representação, no sistema de numeração decimal, de cada um dos seguintes números, escritos na base binária: (a) 11102 (b) (^1101102)
  2. Realize as operações abaixo, sobre números representados no sistema de numeração binário: (a) 1011 + 101 (b) 10100 − 1101
  3. Determine a representação na notação de complemento de 2, com 8 bits, de cada um dos seguintes números: (a) 23 (b) 108
  4. Determine a representação na base decimal de cada um dos seguintes números, representados na notação de complemento de 2, com 8 bits: (a) 11010011 (b) 11110000
  5. Indique como seria feito o cálculo das seguintes operações, em um computador que utiliza notação de complemento de 2 para representação de números e tem palavra com tamanho de 8 bits: (a) 57 + (−118) (b) (−15) + (−46)

1.6 Notas Bibliográcas

Os primeiros estudos em ciência da computação, realizados por volta de 1935, estabeleceram os fundamentos teóricos da área, lançando as bases para a construção dos primeiros computadores. Como resultado desses estudos, foi estabelecida uma caracterização formal para a noção intuitiva de algoritmo, que determinou os limites para o conjunto dos problemas computáveis, possibilitando provar a existência de problemas que não podem ser resolvidos por meio de computação. Ao leitor interessado em saber mais sobre esse assunto, recomendamos a leitura de [?]. Uma discussão interessante sobre a inuência dos recentes resultados da teoria da computação no desenvolvimento tecnológico e cientíco alcançados no século 20 é apresentada em [?] e [?]. Para um bom entendimento sobre os fundamentos teóricos da computação, é necessário algum conhecimento de matemática discreta, que abrange temas como lógica matemática, teoria de con- juntos, relações e funções, indução e recursão. Dois livros excelentes, que abordam esses temas de maneira introdutória, são [?] e [?]. O funcionamento e organização de computadores, descritos brevemente neste capítulo, é discu- tido detalhadamente em diversos livros especícos sobre o assunto, dentre os quais recomendamos [?, ?, ?].

12 Computadores e Programas