




























































































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Os melhores documentos à venda: Trabalhos de alunos formados
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Comunidade
Peça ajuda à comunidade e tire suas dúvidas relacionadas ao estudo
Descubra as melhores universidades em seu país de acordo com os usuários da Docsity
Guias grátis
Baixe gratuitamente nossos guias de estudo, métodos para diminuir a ansiedade, dicas de TCC preparadas pelos professores da Docsity
programação em linguagem c
Tipologia: Manuais, Projetos, Pesquisas
1 / 123
Esta página não é visível na pré-visualização
Não perca as partes importantes!
viii Prefácio
Livros adicionais sobre a linguagem C incluem:
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.
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á:
1.3 Funcionamento e Organização de Computadores 5
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.
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.
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.
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
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.6 Notas Bibliográcas 11
(a) 19 (b) 458
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