program - ufjfin tro d u c~ ao pr o gr ama ao c d a arquit et ura d e compu t adore s e caract er st...

150

Upload: others

Post on 29-Jan-2021

0 views

Category:

Documents


0 download

TRANSCRIPT

  • Programa�c~ao C

    Ivan L. M. Ricarte

    Departamento de Engenharia de Computa�c~ao e Automa�c~ao Industrial

    Faculdade de Engenharia El�etrica e de Computa�c~ao

    Universidade Estadual de Campinas

    c1995,1996 DCA/FEEC/UNICAMP

  • Programa�c~ao C

    DCA/FEEC/UNICAMP 2

  • �Indice

    1 Introdu�c~ao 1

    1.1 A Hist�oria de C : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 1

    1.2 Intera�c~ao entre Programador e Computador : : : : : : : : : : : : : : : : : : : : : : 2

    1.3 Princ��pios de Organiza�c~ao de Computadores : : : : : : : : : : : : : : : : : : : : : : 3

    1.3.1 Representa�c~ao Num�erica : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 5

    1.3.2 Modos de Endere�camento : : : : : : : : : : : : : : : : : : : : : : : : : : : : 7

    1.4 Princ��pios de Sistemas Operacionais : : : : : : : : : : : : : : : : : : : : : : : : : : : 8

    1.5 Desenvolvimento de Software : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 10

    1.5.1 Projeto : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 11

    1.5.2 Programa�c~ao Estruturada : : : : : : : : : : : : : : : : : : : : : : : : : : : : 13

    1.5.3 Codi�ca�c~ao : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 17

    1.5.4 Criando um Programa Execut�avel : : : : : : : : : : : : : : : : : : : : : : : : 18

    1.6 Atividades : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 19

    2 Princ��pios de Programa�c~ao C 21

    2.1 Organiza�c~ao B�asica de Programas C : : : : : : : : : : : : : : : : : : : : : : : : : : 21

    2.2 Tipos de Dados : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 23

    2.3 Declara�c~oes de Vari�aveis : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 25

    2.4 Express~oes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 26

    2.4.1 Express~oes Aritm�eticas : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 27

    2.4.2 Express~oes Condicionais : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 29

    2.4.3 Operadores de Bits : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 30

    2.5 Controle do Fluxo de Execu�c~ao : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 30

    2.6 Invoca�c~ao de Fun�c~oes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 35

    2.6.1 A Fun�c~ao printf : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 39

    2.7 Atividades : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 41

    i

  • �INDICE Programa�c~ao C

    3 Arranjos, Estruturas e Ponteiros 43

    3.1 Arranjos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 43

    3.2 Strings : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 45

    3.3 Estruturas : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 45

    3.3.1 De�ni�c~ao de Estruturas : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 46

    3.3.2 Acesso a Elementos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 47

    3.3.3 Campos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 48

    3.4 Uni~oes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 49

    3.5 Enumera�c~oes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 49

    3.6 De�ni�c~ao de Nomes de Tipos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 51

    3.7 Ponteiros : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 52

    3.7.1 Aritm�etica de Ponteiros : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 53

    3.7.2 Ponteiros e Arranjos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 54

    3.7.3 Ponteiro como Argumento de Fun�c~oes : : : : : : : : : : : : : : : : : : : : : : 56

    3.7.4 Ponteiros e Estruturas : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 58

    3.7.5 Ponteiros para Fun�c~oes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 60

    3.8 Argumentos na Linha de Comando : : : : : : : : : : : : : : : : : : : : : : : : : : : 62

    3.9 Gerência da Mem�oria Livre : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 63

    3.10 O Ponteiro Nulo : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 67

    3.11 Atividades : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 68

    4 Biblioteca Padr~ao 71

    4.1 O Pr�e-processador C : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 71

    4.1.1 A diretiva #include : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 72

    4.1.2 A diretiva #de�ne : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 75

    4.1.3 Compila�c~ao Condicional : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 78

    4.1.4 Outros Recursos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 82

    4.2 Rotinas para Entrada e Sa��da de Dados : : : : : : : : : : : : : : : : : : : : : : : : : 84

    4.2.1 Intera�c~ao com Dispositivos Padr~ao : : : : : : : : : : : : : : : : : : : : : : : 84

    4.2.2 Intera�c~ao com Arquivos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 87

    4.3 Rotinas para Manipula�c~ao de Strings : : : : : : : : : : : : : : : : : : : : : : : : : : 92

    4.4 Rotinas para Intera�c~ao com o Sistema Operacional : : : : : : : : : : : : : : : : : : : 93

    4.5 Exemplo de Aplicativo : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 95

    4.6 Atividades : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 99

    DCA/FEEC/UNICAMP ii

  • Ricarte �INDICE

    5 Introdu�c~ao a C++ 101

    5.1 O Que �E C++ : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 101

    5.2 Programa�c~ao Orientada a Objetos : : : : : : : : : : : : : : : : : : : : : : : : : : : : 102

    5.3 Particularidades de C++ : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 103

    5.3.1 Entrada e Sa��da : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 104

    5.3.2 De�ni�c~ao de Vari�aveis : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 106

    5.3.3 Aloca�c~ao Dinâmica : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 109

    5.3.4 Argumentos de Fun�c~oes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 111

    5.4 Classes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 113

    5.4.1 Construtores e Destrutores : : : : : : : : : : : : : : : : : : : : : : : : : : : : 116

    5.4.2 Objetos e Fun�c~oes : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 117

    5.4.3 Sobrecarga de Operadores : : : : : : : : : : : : : : : : : : : : : : : : : : : : 118

    5.5 Heran�ca : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 119

    5.5.1 Heran�ca de Construtores e Destrutores : : : : : : : : : : : : : : : : : : : : : 120

    5.6 Outros Conceitos : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 121

    5.7 Atividades : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 121

    A Palavras reservadas em C e C++ 125

    B Precedência de Operadores 127

    C Conjunto de caracteres do padr~ao ASCII 129

    D Emacs 133

    E Compilador C 141

    iii c1996

  • �INDICE Programa�c~ao C

    DCA/FEEC/UNICAMP iv

  • Lista de Figuras

    1.1 Arquitetura von Neumann. : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 4

    1.2 Papel do Sistema Operacional. : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 10

    1.3 Processo de evolu�c~ao do software. : : : : : : : : : : : : : : : : : : : : : : : : : : : : 12

    1.4 Estruturas elementares de dados. : : : : : : : : : : : : : : : : : : : : : : : : : : : : 13

    1.5 Mecanismos b�asicos da programa�c~ao estruturada. : : : : : : : : : : : : : : : : : : : 15

    2.1 Estrutura b�asica de um algoritmo. : : : : : : : : : : : : : : : : : : : : : : : : : : : : 22

    2.2 Algoritmo que faz nada. : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 23

    2.3 Sequência em C. : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 31

    2.4 Sele�c~ao com if: : : else em C. : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 32

    2.5 Switch: : : case : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 33

    2.6 Switch: : : case sem break. : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 34

    2.7 Repeti�c~ao em C : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 36

    2.8 Repeti�c~ao em C com for : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 37

    v

  • LISTA DE FIGURAS Programa�c~ao C

    DCA/FEEC/UNICAMP vi

  • Cap��tulo 1

    Introdu�c~ao

    Resumo:

    O objetivo deste texto �e apresentar a base de programa�c~ao em lingua-

    gem C necess�aria para o desenvolvimento de aplica�c~oes do usu�ario,

    que podem ser autocontidos, usar recursos do sistema operacional ou

    recursos de outros aplicativos.

    Neste cap��tulo s~ao introduzidos os conceitos b�asicos que constituem a

    base para a codi�ca�c~ao em qualquer linguagem de programa�c~ao. Estes

    conceitos ser~ao posteriormente revistos sob a �optica da linguagem de

    programa�c~ao C.

    1.1 A Hist�oria de C

    A linguagem de programa�c~ao C foi desenvolvida no in��cio dos anos 70 nos Laborat�orios AT&T

    Bell, nos Estados Unidos. A motiva�c~ao para que o autor de C, Dennis Ritchie, criasse uma nova

    linguagem de programa�c~ao foi o desenvolvimento do sistema operacional Unix. C �e uma ferramenta

    t~ao b�asica que praticamente todas as ferramentas suportadas por Unix e o pr�oprio sistema operacional

    foram desenvolvidas em C.

    C acompanhou o ritmo da distribui�c~ao do sistema operacional Unix, que foi amplamente divul-

    gado e livremente distribu��do na d�ecada de 70. Apesar de haver compiladores para linguagens mais

    \tradicionais" na distribui�c~ao Unix, aos poucos C foi ganhando simpatizantes e adeptos. Atual-

    mente, n~ao h�a d�uvidas de que C �e uma das linguagens de programa�c~ao de maior aceita�c~ao para uma

    ampla classe de aplica�c~oes.

    Um dos grandes atrativos da linguagem C �e o balan�co atingido entre caracter��sticas pr�oximas

    1

  • Introdu�c~ao Programa�c~ao C

    da arquitetura de computadores e caracter��sticas de linguagens de programa�c~ao com alto n��vel de

    abstra�c~ao. O ascendente mais remoto de C, Algol 60, desenvolvida por um comitê internacional, foi

    uma linguagem que buscava um alto grau de abstra�c~ao, com estruturas modulares e sintaxe regu-

    lar. Por Algol ser \abstrata demais", variantes surgiram que buscavam aproximar aquela linguagem

    um pouco mais da m�aquina, tais como CPL (Combined Programming Language), desenvolvida na

    Inglaterra. Esta linguagem era ainda muito complexa, o que di�cultava seu aprendizado e a im-

    plementa�c~ao de bons compiladores. BCPL (Basic CPL) buscava capturar apenas as caracter��sticas

    principais de CPL, e B (desenvolvida por Ken Thompson nos Laborat�orios Bell, em 1970) levava

    este objetivo ainda mais adiante. Entretanto, estas linguagens �caram t~ao \b�asicas" que tinham

    pouca aplica�c~ao direta. Ritchie reincorporou algumas caracter��sticas de alto n��vel �a B, tais como

    suporte a tipos de dados, para criar a linguagem C.

    A simplicidade de C n~ao restringe, no entanto, a potencialidade de suas aplica�c~oes. Blocos desem-

    penhando tarefas muito complexas podem ser criados a partir da combina�c~ao de blocos elementares,

    e este mecanismo de combina�c~ao de partes pode se estender por diversos n��veis. Esta habilidade

    de construir aplica�c~oes complexas a partir de elementos simples �e um dos principais atrativos da

    linguagem.

    O sucesso de C foi t~ao grande que diversas implementa�c~oes de compiladores surgiram, sendo que

    nem todos apresentavam o memso comportamento em pontos espec���cos, devido a caracter��sticas

    distintas arquiteturas de computadores ou a \extens~oes" que se incorporavam �a linguagem. Para

    compatibilizar o desenvolvimento de programas em C, o Instituto Norte-Americano de Padr~oes

    (ANSI) criou em 1983 um comitê com o objetivo de padronizar a linguagem. O resultado deste

    trabalho foi publicado em 1990, e foi prontamente adotado como padr~ao internacional. Al�em de

    padronizar aspectos b�asicos da linguagem, ANSI-C tamb�em de�ne um conjunto de rotinas de suporte

    que, apesar de n~ao ser parte integrante da linguagem, deve ser sempre fornecido pelo compilador.

    1.2 Intera�c~ao entre Programador e Computador

    Um computador nada mais faz do que executar instru�c~oes que lhe s~ao detalhadamente passadas.

    H�a muitas maneiras de um usu�ario de um computador requisitar a execu�c~ao de uma tarefa. Por

    exemplo, tais intera�c~oes podem ocorrer atrav�es de um comando de um sistema operacional (como

    dir em MS-DOS ou ls em Unix para apresentar o conte�udo de um diret�orio) ou atrav�es de intera�c~ao

    com uma interface gr�a�ca (por exemplo, carregar um ��cone de um arquivo para um s��mbolo de uma

    lata de lixo para remover o arquivo do sistema, como em um sistema NeXT).

    As formas de intera�c~ao descritas acima representam apenas distintas interfaces para a execu�c~ao

    DCA/FEEC/UNICAMP 2

  • Ricarte Princ��pios de Organiza�c~ao de Computadores [1.3]

    de programas. Um programa nada mais �e do que uma sequência de instru�c~oes para um computador,

    onde esta sequência de instru�c~oes foi de�nida por um programador. O programador determina as

    instru�c~oes que devem ser executadas em termos de uma linguagem de alto n��vel. Em linguagens

    de alto n��vel, as instru�c~oes s~ao passadas para o computador usando termos que se aproximam da

    linguagem humana, de forma a facilitar a express~ao e compreens~ao das tarefas a executar.

    H�a diversas linguagens de alto n��vel dispon��veis para diversas m�aquinas distintas. Em geral, cada

    linguagem teve uma motiva�c~ao para ser desenvolvida (por exemplo, BASIC para ensinar princ��pios

    de programa�c~ao e Pascal para o ensino de programa�c~ao estruturada, FORTRAN para programa�c~ao

    cient���ca, e lisp para processamento em Inteligência Arti�cial). A linguagem C �e uma destas lingua-

    gens, que foi desenvolvida para facilitar o desenvolvimento de software de sistemas (por exemplos,

    sistemas operacionais).

    O fato de uma linguagem ter sido desenvolvida com uma aplica�c~ao em mente n~ao signi�ca que

    ela n~ao seja adequada para outras aplica�c~oes. Este foi o caso com a linguagem C que, juntamente

    com sua sucessora C++, �e atualmente utilizada para um universo muito amplo de aplica�c~oes. Uma

    das grandes vantagens da linguagem C �e sua exibilidade: um programador C tem �a sua disposi�c~ao

    comandos que permitem desenvolver programas com caracter��sticas de alto n��vel e ao mesmo tempo

    trabalhar em um n��vel muito pr�oximo da arquitetura da m�aquina, de forma a explorar os recursos

    dispon��veis de forma mais e�ciente. Por este motivo, o n�umero de aplica�c~oes desenvolvidas em C e

    C++ (assim como o n�umero de programadores) vêm se ampliando muito em anos recentes.

    1.3 Princ��pios de Organiza�c~ao de Computadores

    Apesar da evolu�c~ao tecnol�ogica que ampliou sensivelmente a capacidade de processamento de

    computadores em anos recentes, a base da organiza�c~ao interna da maior parte dos computadores

    permanece inalterada. Esta organiza�c~ao, conhecida com a Arquitetura von Neumann1 �e diagramati-

    camente apresentada na Figura 1.1.

    Por esta �gura, observa-se que um computador tem três elementos b�asicos:

    processador central (CPU): �e o c�erebro do computador, que decifra instru�c~oes recebidas e as

    executa;

    mem�oria: permite armazenar instru�c~oes e dados;

    1De John von Neumann, matem�atico h�ungaro (1903{1957). Atuou como consultor no Projeto ENIAC, em meadosda d�ecada de 1940.

    3 c1996

  • Introdu�c~ao Programa�c~ao C

    CPU

    Unid. Controle

    Aritmética

    Unid. Lógica eE/SMemória

    Barramento

    Mundo

    ExteriorDados

    Progr.

    Figura 1.1: Arquitetura von Neumann.

    sistema de entrada e sa��da (E/S): estabelece a comunica�c~ao entre o computador e o mundo

    exterior.

    Qualquer intera�c~ao entre uma aplica�c~ao e o computador deve agir sobre um destes três elementos.

    Cada processador entende uma linguagem pr�opria, que reete as instru�c~oes b�asicas que ele pode

    entender. Uma sequência de comandos simb�olicos utilizando este n��vel de instru�c~oes �e um programa

    assembly, que pode ser convertido para os bits que ser~ao entendidos pelo processador (a linguagem

    de m�aquina).

    Na arquitetura von Neumann, um programa (convertido para a linguagem da m�aquina) �e arma-

    zenado na mem�oria. A mem�oria �e acessada pelo processador em unidades chamadas palavras. A

    forma de um processador acessar uma palavra espec���ca dentro da mem�oria �e atrav�es da posi�c~ao

    da palavra dentro da mem�oria; esta posi�c~ao �e chamada de endere�co. Assim, a mem�oria pode ser

    visualizada como uma sequência de palavras ordenadas segundo seus endere�cos.

    A execu�c~ao de uma instru�c~ao de um programa pode ser vista (simpli�cadamente) da seguinte

    forma:

    1. o processador busca a instru�c~ao do programa;

    2. o processador decodi�ca a instru�c~ao, isto �e, descobre que a�c~ao ele deve realizar para aquela

    instru�c~ao;

    3. se esta a�c~ao requer dados adicionais que est~ao em mem�oria, o processador busca tamb�em estes

    dados;

    4. o processador executa a a�c~ao associada �a instru�c~ao;

    DCA/FEEC/UNICAMP 4

  • Ricarte Princ��pios de Organiza�c~ao de Computadores [1.3]

    5. o processador armazena o resultado gerado na mem�oria.

    Este processo �e repetido desde a primeira at�e a �ultima instru�c~ao de um programa.

    Quando uma instru�c~ao requer uma intera�c~ao com algum dispositivo externo (por exemplo, en-

    trada via teclado, apresenta�c~ao de um caracter na tela, acesso a um dado em disco), os dispositivos

    de entrada e sa��da s~ao ativados de forma que ocorre uma intera�c~ao entre estes dispositivos e a

    mem�oria do computador. Quando a opera�c~ao �e de sa��da de dados, palavras s~ao transferidas da

    mem�oria para o dispositivo externo. Quando a opera�c~ao �e de entrada, dados s~ao transferidos do

    dispositivo externo para a mem�oria do computador.

    1.3.1 Representa�c~ao Num�erica

    Internamente, todos os dados s~ao representados no computador como sequências de bits2. Esta �e a

    forma mais conveniente para manipular os dados atrav�es de circuitos digitais, que podem diferenciar

    apenas entre dois estados (on ou o�, verdade ou falso, 0 ou 1). Uma sequência de N bits pode

    representar uma faixa com 2N valores distintos.

    O formato de representa�c~ao interna (ou seja, como uma sequência de bits �e traduzida para um

    valor) pode variar de computador para computador, embora a busca por uma uniformiza�c~ao para a

    representa�c~ao de tipos b�asicos venha ocorrendo nos �ultimos anos. Assim, um caracter usualmente

    ocupa um byte com conte�udo de�nido pelo c�odigo ASCII; um n�umero inteiro tem uma representa�c~ao

    bin�aria, em geral em complemento de dois; e um valor real �e usualmente representado no padr~ao

    IEEE de representa�c~ao em ponto utuante.

    Inteiros sem sinal (unsigned) têm uma representa�c~ao computacional (em n�umeros bin�arios) equi-

    valente �a representa�c~ao usual para n�umeros decimais, ou seja, atrav�es da atribui�c~ao de pesos associa-

    dos �a posi�c~ao de cada bit. Grande parte dos computadores atuais utilizam 32 bits para representar

    n�umeros inteiros, o que permite representar 4:924:967:296 valores distintos. (A gera�c~ao mais recente

    de computadores suporta tamb�em inteiros com 64 bits.) Uma sequência bin�aria

    sn�1sn�2sn�3 : : : s2s1s0

    est�a associada ao valor inteiron�1X

    i=0

    si � 2i

    onde si 2 f0; 1g. O bit sn�1 �e chamado bit mais signi�cativo, enquanto que s0 �e o bit menos

    signi�cativo.

    2Um bit �e um d��gito bin�ario (binary digit), usualmente representado pelos s��mbolos 0 e 1.

    5 c1996

  • Introdu�c~ao Programa�c~ao C

    A representa�c~ao de inteiros com sinal pode usar outros formatos. A forma mais b�asica �e a

    representa�c~ao em sinal e magnitude, onde o bit mais signi�cativo denota o sinal associado ao restante

    da sequência (sn�1 = 1 indicaria que o n�umero �e negativo). Este formato tem a desvantagem de ter

    duas representa�c~oes diferentes para o valor zero, al�em de ter circuitos complicados para suportar

    opera�c~oes b�asicas.

    Outra formato suportado para representar inteiros com sinal �e a representa�c~ao em complemento

    de um. A representa�c~ao para um n�umero negativo neste formato pode ser obtida facilmente a partir

    da representa�c~ao do n�umero positivo correspondente simplesmente complementando cada bit da

    sequência, ou seja, trocando 0's por 1's e 1's por 0's. Apesar de simpli�car circuitos para opera�c~oes

    b�asicas, este formato ainda mant�em duas representa�c~oes distintas para o valor zero.

    O formato mais aceito para inteiros com sinal �e sem d�uvida a representa�c~ao em complemento de

    dois. Para obter a representa�c~ao de um n�umero negativo neste formato, computa-se inicialmente a

    representa�c~ao em complemento de um e adiciona-se 1 ao bit menos signi�cativo. Neste caso, o valor

    inteiro associado �a sequência sn�1 : : : s0 �e

    n�2X

    i=0

    si � 2i � sn�1 � 2

    n:

    Este formato mant�em a simplicidade dos circuitos aritm�eticos e tem apenas uma representa�c~ao

    para o valor zero. Uma caracter��stica que lhe �e peculiar �e o fato de que a faixa de valores repre-

    sent�aveis n~ao �e sim�etrica em torno de 0, havendo um valor negativo a mais que a quantidade de

    valores positivos distintos. Por exemplo, sequências de cinco bits podem representar valores entre

    -16 (10000) e +15 (01111).

    Nem todos valores armazenados em vari�aveis do computador representam n�umeros inteiros. O

    tipo n~ao-num�erico mais suportado em diversas linguagens de programa�c~ao �e o caracter (charac-

    ter). Sequências de caracteres ocorrem t~ao frequentemente em computa�c~ao que recebem um nome

    espec���co, (string).

    Como uma sequência de bits �e traduzida em termos de caracteres tem sido o objeto de diversos

    esfor�cos de padroniza�c~ao, tais como ASCII, ISO-8859, UniCode e o Basic Multilingual Plan (BMP).

    O padr~ao mais aceito �e sem d�uvida o formato ASCII (American Standard for Computer Information

    Exchange). O formato ASCII b�asico permite representar 128 caracteres distintos, entre os quais

    est~ao diversos caracteres de controle (tais com esc, associado �a tecla de escape, e cr, associado

    ao carriage return) e caracteres de pontua�c~ao. Neste formato, os caracteres entre `0' e `9' s~ao

    representados pelos valores hexadecimais 30H a 39H , respectivamente (valores decimais entre 48 e

    57); as letras mai�usculas `A' a `Z', pelos valores de 41H a 5AH ; e as letras min�usculas `a' a `z', pelos

    DCA/FEEC/UNICAMP 6

  • Ricarte Princ��pios de Organiza�c~ao de Computadores [1.3]

    valores de 61H a 7AH .

    Outra forma de representa�c~ao n~ao-inteira corresponde �a representa�c~ao em ponto utuante. Neste

    formato, associado ao conceito de nota�c~ao cient���ca, cada n�umero (real) �e representado por um sinal,

    uma mantissa e um expoente. Entre as in�umeras combina�c~oes poss��veis de formatos de representa�c~ao

    que seguem esta �loso�a b�asica, o padr~ao IEEE-754 tem sido o mais aceito e usualmente suportado

    em hardware (atrav�es das unidades de ponto utuante em co-processadores ou incorporados a CPUs).

    Este formato suporta representa�c~oes de n�umeros reais em precis~ao simples (32 bits, dos quais 8 para

    a representa�c~ao do expoente e 23 para a representa�c~ao da mantissa) e em precis~ao dupla (64 bits,

    sendo 11 para o expoente e 53 para a mantissa). H�a tamb�em representa�c~oes especiais para os valores

    �1, +1 e NaN (Not a Number, associado ao resultado de opera�c~oes sem signi�cado matem�atico,

    tal como a divis~ao de zero por zero).

    1.3.2 Modos de Endere�camento

    Vari�aveis de um programa de computador s~ao armazenadas em mem�oria, e referências a estas

    vari�aveis devem ser traduzidas internamente em termos de seus endere�cos. H�a diversas maneiras

    poss��veis que computadores podem usar para especi�car endere�cos em suas instru�c~oes; estas formas

    s~ao os chamados modos de endere�camento. Embora o n�umero de combina�c~oes poss��veis para a

    especi�ca�c~ao de endere�cos possa ser praticamente sem �m, processadores mais recentes (da linha

    RISC3) suportam apenas as formas mais b�asicas de endere�camento, descritas a seguir.

    No modo de endere�camento direto o endere�co de uma vari�avel �e especi�cado diretamente na

    instru�c~ao. Esta �e a forma mais intuitiva de endere�camento.

    No modo de endere�camento indexado, o endere�co �e computado a partir da soma de um endere�co

    base (mantido em um registro da CPU) e um deslocamento. Esta forma de endere�camento �e perfei-

    tamente adequada para acesso a sequências de valores, tais como suportadas por vetores num�ericos

    ou strings de caracteres.

    O terceiro modo b�asico �e o endere�camento indireto, onde o endere�co especi�cado em uma ins-

    tru�c~ao n~ao �e o endere�co da vari�avel mas sim um endere�co onde o endere�co da vari�avel poder�a

    ser obtido. Este modo de endere�camento permite suportar um mecanismo de acesso dinâmico, ou

    seja, uma mesma instru�c~ao pode operar sobre vari�aveis distintas. Em termos de linguagem de

    programa�c~ao, este modo de endere�camento est�a usualmente associado ao conceito de apontadores.

    3Reduced Instruction Set Computers, ou seja, computadores com um pequeno n�umero de instru�c~oes.

    7 c1996

  • Introdu�c~ao Programa�c~ao C

    1.4 Princ��pios de Sistemas Operacionais

    O Sistema Operacional �e um programa supervisor que estabelece uma camada entre o hardware

    do computador e aplica�c~oes de usu�arios. Uma de suas fun�c~oes �e estabelecer uma interface de software

    uniforme entre o computador e outros programas do sistema e programas de aplica�c~ao de usu�arios.

    Outra fun�c~ao fundamental de um sistema operacional �e gerenciar os recursos de um computador de

    forma a promover sua e�ciente utiliza�c~ao. Exemplos de sistemas operacionais s~ao MS-DOS, OS/2 e

    Linux para computadores pessoais e sistemas Unix para esta�c~oes de trabalho.

    A unidade b�asica de computa�c~ao gerenciada por um sistema operacional �e um processo, que

    �e basicamente um programa em execu�c~ao. Os recursos requeridos por um processo, tais como

    espa�co em mem�oria para guardar os dados e as instru�c~oes do programa, s~ao alocados pelo sistema

    operacional. Um processo passa a existir a partir do momento em que um programa foi ativado, e

    deixa de existir quando a execu�c~ao do programa �e encerrada. Neste ponto, os recursos que lhe foram

    alocados pelo sistema operacional s~ao liberados.

    Outra fun�c~ao associada ao sistema operacional �e a gerência dos recursos de mem�oria do com-

    putador. Em um sistema onde mais de um programa pode estar sendo executado simultaneamente,

    os diversos processos est~ao competindo pelos recursos de mem�oria, que s~ao limitados. �E tarefa do

    sistema operacional coordenar estes recursos de forma que, em m�edia, todos os processos tenham

    tempo de execu�c~ao em limites razo�aveis.

    Do ponto de vista l�ogico, a �area de mem�oria de um processo �e dividida em segmentos indepen-

    dentes. No sistema operacional Unix, por exemplo, h�a três segmentos de mem�oria associados a um

    processo: texto, dados e pilha.

    O segmento de texto cont�em as instru�c~oes do programa, e geralmente �e uma �area protegida

    pelo sistema operacional | isto �e, um programa de um usu�ario n~ao pode modi�car diretamente o

    conte�udo ou o tamanho desta �area. Uma tentativa de modi�ca�c~ao em uma palavra desta �area ir�a

    causar um erro de execu�c~ao de um programa, tal com segmentation fault. Deve �car claro que o

    conte�udo desta �area n~ao �e o texto das instru�c~oes em uma linguagem de alto n��vel (C, por exemplo),

    mas sim sua tradu�c~ao em termos de linguagem de m�aquina. Esta tradu�c~ao �e realizada pelo programa

    compilador, um dos aplicativos em um sistema operacional.

    O segmento de dados armazena dados e vari�aveis do programa. Esta �e uma �area cujo conte�udo

    pode ser modi�cado (o valor de vari�aveis) e cujo tamanho pode ser alterado. O segmento de dados

    pode ser conceitualmente dividido em duas sub-�areas, uma �area est�atica, com dimens~ao conhecida

    no momento da compila�c~ao de um programa, e uma �area dinâmica ou livre, que pode crescer ou

    encolher durante a execu�c~ao do programa. Entretanto, deve-se observar que este tamanho n~ao pode

    DCA/FEEC/UNICAMP 8

  • Ricarte Princ��pios de Sistemas Operacionais [1.4]

    crescer inde�nidamente, havendo limites para a mem�oria total associada a um processo.

    O segmento de pilha mant�em as informa�c~oes tempor�arias de um processo. Este segmento tamb�em

    tem conte�udo e tamanho vari�aveis, embora tamb�em haja limites para a expans~ao da pilha. O

    crescimento ilimitado da pilha pode causar um erro de execu�c~ao tal como stack overow.

    Outro recurso gerenciado pelo sistema operacional �e o sistema de arquivos, que permite armazenar

    dados e acess�a-los de discos sob a forma de arquivos. Esta �e uma atividade importante do sistema

    operacional, uma vez que o acesso a discos magn�eticos pode se tornar um ponto cr��tico no desempenho

    de aplica�c~oes manipulando muitos dados.

    Uma forma que o sistema operacional suporta para melhorar a e�ciência de acesso a arquivos �e

    manter, em mem�oria principal, parte da informa�c~ao sobre arquivos em disco. Para tanto, o sistema

    operacional mant�em uma tabela de arquivos. Esta tabela mant�em informa�c~oes que permitem agilizar

    o acesso aos dados do arquivo, al�em de manter informa�c~oes de suporte (por exemplo, indica�c~ao de

    qual a posi�c~ao corrente dentro do arquivo). Uma aplica�c~ao pode referenciar um arquivo presente

    nesta tabela atrav�es de um descritor de arquivo, um n�umero inteiro indicando uma posi�c~ao na tabela

    alocada pelo sistema operacional.

    O sistema operacional suporta rotinas para requisitar a abertura de um arquivo (alocando-lhe

    uma entrada na tabela de arquivos), para fechar um arquivo aberto (liberando espa�co nesta tabela),

    para transferir dados entre o arquivo e a mem�oria principal, e para rotinas de suporte �a manipula�c~ao

    de arquivos. A seguir, s~ao apresentadas algumas das principais opera�c~oes suportadas pelo sistema

    operacional Unix para a manipula�c~ao de arquivos:

    open abrir arquivo

    argumentos: nome do arquivo, modo de abertura

    retorno: descritor do arquivo ou indicador de erro

    read transferir bytes do arquivo para uma �area em mem�oria

    argumentos: descritor do arquivo, endere�co da �area em mem�oria, n�umero de bytes

    retorno: n�umero de bytes efetivamente lidos do arquivo ou indicador de erro

    write transferir bytes de uma �area em mem�oria para o arquivo

    argumentos: descritor do arquivo, endere�co da �area em mem�oria, n�umero de bytes

    retorno: n�umero de bytes efetivamente escritos para o arquivo ou indicador de erro

    close fechar o arquivo

    argumento: descritor do arquivo

    retorno: indicador de sucesso ou erro

    9 c1996

  • Introdu�c~ao Programa�c~ao C

    Em Unix, a manipula�c~ao de dispositivos de entrada e sa��da (impressoras, teclados, monitores) �e

    tratada uniformemente sob a forma de arquivos. Por exemplo, o teclado est�a associado a um arquivo

    padr~ao de entrada (descritor 0), enquanto que o monitor est�a associado ao arquivo padr~ao de sa��da

    (descritor 1) e tamb�em ao arquivo padr~ao de mensagens de erro (descritor 2).

    A Figura 1.2 apresenta o papel do sistema operacional como interface entre aplicativos e o hard-

    ware. Aplicativos podem ser tanto os programas desenvolvidos pelo usu�ario como outras aplica�c~oes

    que suportam ou facilitam o desenvolvimento das aplica�c~oes do usu�ario.

    Rotinas de

    Suporte

    Hardware

    Sistema Operacional

    Aplicação

    Figura 1.2: Papel do Sistema Operacional.

    O objetivo deste curso �e fornecer a base de programa�c~ao em linguagem C necess�aria para o

    desenvolvimento de aplica�c~oes do usu�ario, que podem ser autocontidos, usar recursos do sistema

    operacional ou recursos de outros aplicativos. A seguir, alguns aspectos ligados ao desenvolvimento

    deste tipo de aplica�c~oes s~ao abordados.

    1.5 Desenvolvimento de Software

    N~ao h�a d�uvidas hoje em dia quanto �a importância do software no desenvolvimento dos mais

    diversos sistemas. Com esta evolu�c~ao do papel do software em sistemas computacionais, veio tamb�em

    uma maior complexidade de programas e uma maior preocupa�c~ao em desenvolver programas que

    pudessem ser facilmente entendidos e modi�cados (se necess�ario), n~ao apenas pelo autor do programa

    mas tamb�em por outros programadores. A disciplina que estuda o desenvolvimento de bom software

    �e conhecida como Engenharia de Software.

    A Engenharia de Software estabelece alguns princ��pios de desenvolvimento que independem da

    linguagem de programa�c~ao adotada. Estes princ��pios s~ao utilizados nas três fases da vida de um

    DCA/FEEC/UNICAMP 10

  • Ricarte Desenvolvimento de Software [1.5]

    programa, que s~ao:

    De�ni�c~ao: estuda o que deve ser feito pelo programa, incluindo an�alises do sistema e do problema

    a ser resolvido;

    Desenvolvimento: incorpora o projeto do programa (por exemplo, uma descri�c~ao do algoritmo e

    estruturas necess�arias), a codi�ca�c~ao (tradu�c~ao do projeto em termos de uma linguagem de

    programa�c~ao) e testes do programa; e

    Manuten�c~ao: �e a fase de mudan�cas decorrentes da corre�c~ao de erros e atualiza�c~oes do programa.

    A fase de desenvolvimento costuma tomar a maior parte do ciclo de vida de cria�c~ao de um

    software. Nesta fase s~ao tomadas decis~oes que podem afetar sensivelmente o custo e a qualidade do

    software gerado.

    Uma vez estabelecida a funcionalidade do software que se deseja implementar na fase de de�ni�c~ao,

    a fase de desenvolvimento propriamente dita pode ser iniciada. Esta fase pode ser dividida em três

    etapas principais, que s~ao projeto, codi�ca�c~ao e teste. A seguir, ser~ao destacados alguns aspectos

    ligados ao desenvolvimento de software, que ser�a o principal enfoque deste curso.

    1.5.1 Projeto

    O projeto de software pode ser subdividido em dois grandes passos, projeto preliminar e projeto

    detalhado. O projeto preliminar preocupa-se em transformar os requisitos especi�cados na fase de

    an�alise em arquiteturas de dados e de software. O projeto detalhado re�na estas representa�c~oes de

    arquitetura em estruturas de dados detalhadas e em representa�c~oes algor��tmicas do software.

    Uma das estrat�egias de projeto mais utilizadas �e o desenvolvimento top-down. Neste tipo de

    desenvolvimento, trabalha-se com o conceito de re�namento de descri�c~oes do software em distintos

    n��veis abstra�c~ao. O conceito de abstra�c~ao est�a relacionado com esconder informa�c~ao sobre os de-

    talhes. No n��vel mais alto de abstra�c~ao, praticamente nenhuma informa�c~ao �e detalhada sobre como

    uma dada tarefa ser�a implementada | simplesmente descreve-se qual �e a tarefa. Em etapas suces-

    sivas de re�namento, o projetista do software vai elaborando sobre a descri�c~ao da etapa anterior,

    fornecendo cada vez mais detalhes sobre como realizar a tarefa.

    O resultado natural do desenvolvimento top-down �e uma estrutura de software, que representa

    a organiza�c~ao dos distintos componentes (ou m�odulos) do programa. A Figura 1.3 ilustra de forma

    simpli�cada o processo de passagem de um problema a uma estrutura de software para sua solu�c~ao.

    Observe nesta �gura que a solu�c~ao pode n~ao ser �unica: dependendo de como o projeto �e desenvolvido

    e das decis~oes tomadas, distintas estruturas podem resultar.

    11 c1996

  • Introdu�c~ao Programa�c~ao C

    S1 S2 S3 S4 S1

    S2 S3

    S4

    "Problema"

    P2P3

    P4P1

    S1S3

    S4

    S2

    Solucao

    por software

    Possiveis estruturas de software

    Figura 1.3: Processo de evolu�c~ao do software.

    DCA/FEEC/UNICAMP 12

  • Ricarte Desenvolvimento de Software [1.5]

    Outro aspecto t~ao importante quanto a estrutura de software �e a estrutura de dados, que �e uma

    representa�c~ao do relacionamento l�ogico entre os elementos de dados individuais. As estruturas de

    dados utilizadas de�nem a organiza�c~ao, m�etodos de acesso e alternativas de processamento para a

    informa�c~ao manipulada pelo programa. Embora a estrutura �nal possa ser t~ao complexa quanto o

    projetista deseja, h�a alguns blocos b�asicos (Figura 1.4) que permitem construir as estruturas mais

    so�sticadas.

    A estrutura de dao mais simples �e um escalar, que representa um elemento simples de informa�c~ao

    que pode ser acessado atrav�es de um identi�cador. Elementos escalares organizados como um

    grupo cont��guo constituem um vetor sequencial, cujos elementos podem ser acessados atrav�es de um

    identi�cador em associa�c~ao com um ��ndice. Elementos n~ao-cont��guos podem ser agrupados atrav�es

    de uma lista ligada, cuja unidade de acesso �e um n�o que cont�em um item de dado (escalar ou n~ao)

    e um ponteiro para indicar o pr�oximo n�o na lista.

    Escalar Vetor sequencial

    . . .

    Lista ligada

    Figura 1.4: Estruturas elementares de dados.

    Uma vez estabelecidas as estruturas de software e de dados do programa, o detalhamento do

    projeto pode prosseguir com o projeto procedimental, onde s~ao de�nidos os detalhes dos algoritmos

    que ser~ao utilizados para implementar o programa. Um algoritmo �e uma solu�c~ao passo-a-passo

    para a resolu�c~ao do problema especi�cado. Em princ��pio, algoritmos poderiam ser descritos usando

    linguagem natural (português, por exemplo). Entretanto, o uso da linguagem natural para descrever

    algoritmos geralmente leva a ambiguidades, de modo que se utilizam normalmente linguagens mais

    restritas para a descri�c~ao dos passos de um algoritmo. Algumas formas de especi�ca�c~ao destas

    linguagens s~ao descritas na sequência.

    1.5.2 Programa�c~ao Estruturada

    A programa�c~ao estruturada estabelece uma disciplina de desenvolvimento de algoritmos que

    facilita a compreens~ao de programas. O princ��pio b�asico de programa�c~ao estruturada �e que um pro-

    13 c1996

  • Introdu�c~ao Programa�c~ao C

    grama �e composto por blocos elementares que se interligam atrav�es de três mecanismos b�asicos, que

    s~ao sequência, sele�c~ao e repeti�c~ao. Cada uma destas constru�c~oes tem um ponto de in��cio (o topo do

    bloco) e um ponto de t�ermino (o �m do bloco) de execu�c~ao. Qualquer algoritmo, independentemente

    da �area de aplica�c~ao e de sua complexidade, pode ser descrito atrav�es destes mecanismos b�asicos.

    Um dos mecanismos mais utilizados para a representa�c~ao de algoritmos �e o uxograma. Em

    um uxograma, o retângulo indica um passo do processamento (uma tarefa), o losango indica uma

    condi�c~ao l�ogica e as setas mostram o uxo de controle. A Figura 1.5 mostra os s��mbolos utilizados

    para representar as principais formas de constru�c~ao estruturada de algoritmos.

    Sequência (Figura 1.5(a)) implementa os passos de processamento necess�arios para descrever

    qualquer programa. Por exemplo, um segmento de programa da forma \fa�ca primeiro a Tarefa a e

    depois a Tarefa b" seria representado por uma sequência de dois retângulos. Uma nota�c~ao textual

    equivalente poderia ser obtida atrav�es de uma pseudo-linguagem que se restringisse a constru�c~oes

    estruturadas, como em

    Tarefa a;

    Tarefa b;

    Sele�c~ao especi�ca a possibilidade de selecionar o uxo de execu�c~ao do processamento baseado

    em ocorrências l�ogicas. H�a duas formas b�asicas de condi�c~ao. A primeira forma �e a constru�c~ao

    IF-THEN-ELSE (Figura 1.5(b)), que permite representar uxos da forma \se a condi�c~ao x for ver-

    dadeira, fa�ca a Tarefa a; sen~ao (isto �e, se a condi�c~ao x for falsa), fa�ca a Tarefa b." As duas setas

    que saem do losango de condi�c~ao no uxograma recebem r�otulos T e F para indicar o uxo de

    execu�c~ao quando a condi�c~ao especi�cada �e verdadeira ou falsa, respectivamente. O retângulo sob

    a seta rotulada T normalmente �e denominado a parte then da constru�c~ao, enquanto que o outro

    retângulo �e denominado parte else. Em termos de pseudo-linguagem, a constru�c~ao equivalente pode

    ser descrita como

    IF (x)

    THEN Tarefa a;

    ELSE Tarefa c;

    ENDIF

    A outra forma de sele�c~ao estende o n�umero de condi�c~oes que podem ser testadas para de�nir

    o uxo de execu�c~ao. Esta constru�c~ao, CASE-SELECT (Figura 1.5(c)), permite representar uxos da

    forma \se a vari�avel v tem o valor x, fa�ca a Tarefa a; se v tem o valor y, fa�ca a Tarefa b; e se tem o valor

    z, fa�ca a Tarefa c." Uma poss��vel representa�c~ao para tal constru�c~ao em termos de pseudo-linguagem

    �e:

    DCA/FEEC/UNICAMP 14

  • Ricarte Desenvolvimento de Software [1.5]

    (a) (b)

    ...

    (c)

    (d) (e)

    T F T

    T

    T

    F

    F

    F

    F

    T

    T

    F

    Figura 1.5: Representa�c~ao dos mecanismos b�asicos da programa�c~ao estruturada: (a) sequência; (b)sele�c~ao IF; (c) sele�c~ao CASE; (d) repeti�c~ao WHILE; (e) repeti�c~ao DO.

    15 c1996

  • Introdu�c~ao Programa�c~ao C

    CASE OF v:

    WHEN x SELECT Tarefa a;

    WHEN y SELECT Tarefa b;

    WHEN z SELECT Tarefa c;

    DEFAULT: Tarefa d;

    ENDCASE

    Neste exemplo em pseudo-linguagem, ilustra-se a inclus~ao de uma condi�c~ao default, que indica qual

    deve ser a a�c~ao executada (no caso, Tarefa d) quando a vari�avel assume um valor n~ao explicitamente

    especi�cado pelo programador.

    Observe que a constru�c~ao case-select n~ao �e essencial, uma vez que ela pode ser representada

    em termos de if-then-else, como em

    IF (v = x)

    THEN Tarefa a;

    ELSE IF (v = y)

    THEN Tarefa b;

    ELSE IF (v = z)

    THEN Tarefa c;

    ELSE Tarefa d;

    ENDIF

    ENDIF

    ENDIF

    Entretanto, a utiliza�c~ao deste tipo de estrutura simpli�ca a express~ao de situa�c~oes que ocorrem

    frequentemente em programas (por exemplo, selecionar a�c~oes dependendo de uma op�c~ao escolhida

    em um menu) sem ter que recorrer ao aninhamento excessivo de condi�c~oes da forma if-then-else.

    Repeti�c~ao permite a execu�c~ao repetitiva de segmentos do programa. Na forma b�asica de repeti�c~ao,

    WHILE-DO (Figura 1.5(d)), uma condi�c~ao x �e veri�cada. caso seja verdadeira, ent~ao uma Tarefa

    a �e executada, e ent~ao a condi�c~ao �e reavaliada. Enquanto a condi�c~ao for verdadeira, a tarefa �e

    repetidamente executada. Em termos da pseudo-linguagem, esta constru�c~ao pode ser representada

    por

    WHILE (x) DO

    Tarefa a;

    ENDWHILE

    DCA/FEEC/UNICAMP 16

  • Ricarte Desenvolvimento de Software [1.5]

    Uma ligeira varia�c~ao desta constru�c~ao �e apresentada na Figura 1.5(e), onde inicialmente a tarefa

    �e executada e apenas ent~ao a condi�c~ao de repeti�c~ao �e avaliada. Esta variante, DO-WHILE, pode ser

    expressa em termos da pseudo-linguagem por

    DO

    Tarefa a;

    WHILE (x);

    A estrat�egia de desenvolvimento top-down pode tamb�em ser utilizada na descri�c~ao algor��tmica de

    procedimentos. Neste caso, um retângulo pode descrever uma tarefa t~ao complexa quanto necess�ario,

    sendo que esta tarefa pode ser posteriormente descrita em termos de outro(s) uxograma(s). Em

    geral, s~ao aplicados tantos re�namentos quanto necess�ario at�e o ponto em que uma tarefa possa ser

    facilmente descrita em termos das constru�c~oes suportadas pela linguagem de codi�ca�c~ao.

    1.5.3 Codi�ca�c~ao

    A etapa de codi�ca�c~ao traduz a representa�c~ao do projeto detalhado em termos de uma lingua-

    gem de programa�c~ao. Normalmente s~ao utilizadas linguagens de alto n��vel, que podem ent~ao ser

    automaticamente traduzidas para a linguagem de m�aquina pelo processo de compila�c~ao.

    A tradu�c~ao de uma especi�ca�c~ao de um programa para uma linguagem de programa�c~ao pode

    resultar em programas incompreens��veis se n~ao houver um cuidado na preserva�c~ao da informa�c~ao

    presente. As linhas gerais que est~ao a seguir buscam estabelecer uma disciplina de codi�ca�c~ao que,

    se seguida, facilita o entendimento e manuten�c~ao de programas.

    C�odigo deve ser acima de tudo claro. Os compiladores modernos fazem um �otimo trabalho de

    otimiza�c~ao de c�odigo, de forma que n~ao h�a necessidade do programador �car se preocupando em usar

    pequenos \truques" para economizar algumas instru�c~oes no c�odigo de m�aquina | provavelmente o

    compilador j�a faria isto para o programador. A preocupa�c~ao com a otimiza�c~ao de c�odigo s�o deve

    existir ap�os a detec�c~ao da necessidade real desta otimiza�c~ao, e ela deve se restringir ao segmento do

    programa onde o problema de desempenho foi localizado.

    Nomes de identi�cadores (vari�aveis, procedimentos) devem denotar claramente o signi�cado do

    identi�cador. Linguagens de programa�c~ao modernas raramente limitam o n�umero de caracteres

    que um identi�cador pode ter, de forma que n~ao faz sentido restringir este tamanho. Compare as

    duas linhas de c�odigo a seguir, e observe como nomes claros podem facilitar a compreens~ao de um

    programa:

    d = v*t;

    distancia = velocidade * tempo;

    17 c1996

  • Introdu�c~ao Programa�c~ao C

    O uso de coment�arios deve ser usado como forma de documenta�c~ao interna de um programa.

    O excesso de coment�arios n~ao �e recomendado, pois isto pode prejudicar a leitura de um programa.

    Entretanto, h�a coment�arios que devem estar presentes em qualquer programa, tais como

    � Coment�arios de pr�ologo, que aparecem no in��cio de cada m�odulo. Devem indicar a �nalidade

    do m�odulo, uma hist�oria de desenvolvimento (autor e data de cria�c~ao e modi�ca�c~oes), e uma

    descri�c~ao das vari�aveis globais (se houver);

    � Coment�arios de procedimento, que aparecem antes de cada fun�c~ao indicando seu prop�osito,

    uma descri�c~ao dos argumentos e valores de retorno;

    � Coment�arios descritivos, que descrevem blocos de c�odigo.

    Coment�arios devem ser facilmente diferenci�aveis de c�odigo, seja atrav�es do uso de linhas em branco,

    seja atrav�es de tabula�c~oes. �E importante que coment�arios sejam corretos, uma vez que um co-

    ment�ario errôneo pode di�cultar mais ainda o entendimento de um programa do que se n~ao houvesse

    coment�ario nenhum.

    Na especi�ca�c~ao das constru�c~oes estruturadas, use tabula�c~oes para indicar blocos de distintos

    n��veis. Evite sempre que poss��vel o uso de condi�c~oes de teste complicadas e o aninhamento muito pro-

    fundo de condi�c~oes de teste. Use parênteses para deixar claro como express~oes l�ogicas e aritm�eticas

    ser~ao computadas.

    Com rela�c~ao a instru�c~oes de entrada e sa��da, todos os dados de entrada devem ser validados.

    O formato de entrada deve ser t~ao simples quanto poss��vel e, no caso de entrada interativa, o

    usu�ario deve receber uma indica�c~ao de que o programa est�a aguardando dados. Da mesma forma,

    a apresenta�c~ao de resultados deve ser clara, com indica�c~ao sobre o que est�a sendo apresentado.

    Finalmente, teste o valor de retorno de qualquer rotina que possa retornar um erro, tomando as

    a�c~oes que forem necess�arias para minimizar o efeito do erro.

    1.5.4 Criando um Programa Execut�avel

    Para que o computador entenda um programa escrito em uma linguagem de alto n��vel �e preciso

    traduzir as instru�c~oes deste programa para a linguagem do computador. A primeira etapa �e a cria�c~ao

    de um arquivo com o chamado c�odigo fonte. O c�odigo fonte cont�em as fun�c~oes com instru�c~oes em

    linguagem C, que ser~ao posteriormente compiladas em um arquivo com c�odigo objeto.

    Para criar um arquivo com o c�odigo fonte do programa, �e preciso usar um editor de programas

    ou editor de textos (desde que seja poss��vel criar um arquivo sem caracteres de formata�c~ao).

    DCA/FEEC/UNICAMP 18

  • Ricarte Atividades [1.6]

    Ap�os criado o arquivo com c�odigo fonte, este ser�a passado como entrada para o programa compi-

    lador. O compilador C executa a tradu�c~ao do c�odigo fonte para um arquivo execut�avel em diversas

    etapas, quais sejam:

    Pr�e-processador: nesta primeira etapa, algumas abreviaturas que o programador usou em seu

    c�odigo fonte s~ao traduzidas para os comandos (n~ao abreviados) da linguagem C. O resultado

    desta fase �e ainda um c�odigo fonte, por�em expandido. Estas abreviaturas s~ao introduzidas no

    c�odigo fonte atrav�es das diretivas do pr�e-processador ;

    Compilador (propriamente dito): nesta segunda etapa, o c�odigo fonte �e traduzido em linguagem

    assembly da m�aquina para a qual ele est�a sendo compilado. Nesta etapa veri�ca-se se o c�odigo

    fonte est�a sintaticamente correto, isto �e, se as regras da linguagem de programa�c~ao C foram

    seguidas. Otimiza�c~oes sobre o c�odigo fonte s~ao realizadas nesta fase;

    Montador: usando este aplicativo do sistema, o c�odigo assembly (ainda um arquivo texto) �e tradu-

    zido em linguagem de m�aquina (um arquivo bin�ario). O resultado �e o c�odigo objeto reloc�avel,

    um formato intermedi�ario que n~ao pode ser lido pelo usu�ario e n~ao pode ser executado pelo

    sistema;

    Ligador: este aplicativo do sistema executa a fase �nal da cria�c~ao de um arquivo execut�avel. Nesta

    etapa, o c�odigo objeto reloc�avel do programa criado pelo usu�ario �e ligado a rotinas internas do

    sistema (e possivelmente rotinas de outras aplicativos) para criar uma unidade independente,

    um arquivo com c�odigo execut�avel.

    Em um sistema operacional como Unix, estas etapas s~ao transparentes para o usu�ario, pois o

    aplicativo compilador C realiza as quatro etapas internamente. Assim, o processo de cria�c~ao de um

    programa C envolve a edi�c~ao (cria�c~ao do c�odigo fonte), a compila�c~ao (cria�c~ao do c�odigo execut�avel)

    e a execu�c~ao do programa. Casa haja erros de sintaxe, o programa execut�avel n~ao ser�a gerado, e

    deve-se voltar so processo de edi�c~ao para corrigir estes erros. Caso o programa execut�avel tenha

    sido gerado mas apresente resultados imprevistos, o ciclo tamb�em deve se repetir a partir da edi�c~ao.

    1.6 Atividades

    Atividade 1 Apresente a representa�c~ao bin�aria em complemento de dois (8 bits) para os seguintes

    valores decimais inteiros:

    (a) 25

    19 c1996

  • Introdu�c~ao Programa�c~ao C

    (b) -31

    (c) 74

    (d) -127

    Atividade 2 Apresente o valor decimal associado aos seguintes inteiros em representa�c~ao bin�aria

    em complemento de dois:

    (a) 10110110

    (b) 01011101

    (c) 00011111

    (d) 11111111

    Atividade 3 Desenvolva algoritmos para resolver os seguintes problemas. Indique quais parâmetros

    s~ao necess�arios, diferenciando entre aqueles que s~ao constantes e aqueles que s~ao

    vari�aveis.

    (a) Converter um valor dado em d�olares para reais ou um valor dado em reais para

    d�olares.

    (b) Dado o nome de um arquivo contendo texto, contar e apresentar o n�umero de

    caracteres no arquivo.

    (c) Dado o nome de um arquivo contendo texto, apresentar na tela o seu conte�udo.

    Atividade 4 Investigue no manual do seu sistema operacional (por exemplo, a se�c~ao 2 do man em

    Unix) que tipo de atividades s~ao suportadas na interface de servi�cos para programas

    (os system calls). Selecione cinco opera�c~oes e classi�que-as de acordo com o recurso

    do computador que estar�a sendo utilizado.

    DCA/FEEC/UNICAMP 20

  • Cap��tulo 2

    Princ��pios de Programa�c~ao C

    Resumo:

    Neste cap��tulo, os fundamentos de programa�c~ao em linguagem C ser~ao

    introduzidos. Particularmente, ser�a enfatizada a tradu�c~ao de algorit-

    mos para comandos e estruturas da linguagem.

    2.1 Organiza�c~ao B�asica de Programas C

    Na linguagem C, todo algoritmo deve ser traduzido para uma fun�c~ao. Uma fun�c~ao nada mais �e

    do que um conjunto de express~oes da linguagem C (possivelmente incluindo invoca�c~oes ou chamadas

    para outras fun�c~oes) com um nome e argumentos associados. Em geral, a de�ni�c~ao de uma fun�c~ao

    C tem a forma

    tipo nome(lista de argumentos) {

    declaracoes;

    comandos;

    }

    O tipo indica o valor de retorno de uma fun�c~ao, podendo assumir qualquer valor v�alido da

    linguagem C (que ser~ao vistos adiante). O tipo da fun�c~ao pode ser omitido, sendo que neste caso o

    compilador ir�a assumir que o tipo int (inteiro) ser�a retornado.

    Nome �e o r�otulo dado �a fun�c~ao, que em geral deve expressar de alguma forma o que a fun�c~ao

    realiza. Nos compiladores mais antigos, o n�umero de caracteres em um nome era limitado (em geral,

    a 6 ou 8 caracteres). Atualmente, n~ao h�a restri�c~oes ao comprimento de um nome, de forma que

    nomes signi�cativos devem ser preferencialmente utilizados. Em C, todo nome que estiver seguido

    21

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    por parênteses ser�a reconhecido como o nome de uma fun�c~ao. A lista de argumentos que �ca no

    interior dos parênteses indica que valores a fun�c~ao precisa para realizar suas tarefas. Quando nenhum

    valor �e necess�ario para a fun�c~ao, a lista ser�a vazia, como em ( ).

    O que se segue na de�ni�c~ao da fun�c~ao, delimitado entre chaves f e g, �e o corpo da fun�c~ao.

    Declara�c~oes correspondem �as vari�aveis internas que ser~ao utilizadas pela fun�c~ao, e comandos imple-

    mentam o algoritmo associado �a fun�c~ao.

    Todo algoritmo (e consequentemente todo programa) deve ter um ponto de in��cio e um ponto

    de �m de execu�c~ao. Na Figura 2.1, esta estrutura b�asica de um algoritmo �e ilustrada | onde h�a

    uma \nuvem" faz alguma coisa, deve ser inserido o corpo do algoritmo que descreve a fun�c~ao a ser

    realizada.

    start

    Faz algumacoisa

    end

    Figura 2.1: Estrutura b�asica de um algoritmo.

    Um programa C �e basicamente um conjunto de fun�c~oes. O ponto de in��cio e t�ermino de execu�c~ao

    de um programa C est�a associado com uma fun�c~ao com um nome especial: a fun�c~aomain (principal).

    O menor programa C que pode ser compilado corretamente �e um programa que nada faz (Figura 2.2).

    Este programa C �e:

    main( ) {

    }

    Neste caso, a fun�c~ao de nome main �e de�nida sem nenhum comando. Neste ponto, algumas

    observa�c~oes devem ser feitas:

    � Todo programa C tem que ter pelo menos uma fun�c~ao.

    DCA/FEEC/UNICAMP 22

  • Ricarte Tipos de Dados [2.2]

    end

    start

    Figura 2.2: Algoritmo que faz nada.

    � Pelo menos uma fun�c~ao do programa C tem o nome main | esta fun�c~ao indica o ponto onde

    se iniciar�a a execu�c~ao do programa, e ap�os executado seu �ultimo comando o programa �naliza

    sua execu�c~ao.

    Ao contr�ario do que ocorre em Pascal ou FORTRAN, que diferenciam procedimentos (subrotinas)

    de fun�c~oes, em C h�a apenas fun�c~oes | mesmo que elas n~ao retornem nenhum valor.

    2.2 Tipos de Dados

    A linguagem C suporta os tipos de dados b�asicos usualmente suportados pelos computadores.

    Na linguagem padr~ao, os tipos b�asicos suportados s~ao:

    char caracter

    int inteiro

    oat real

    double real de precis~ao dupla

    O tipo char ocupa um �unico byte, sendo adequado para armazenar um caracter do conjunto

    ASCII e pequenos valores inteiros.

    O tipo int representa um valor inteiro que pode ser positivo ou negativo. O n�umero de bytes

    ocupado por este tipo (e consequentemente a faixa de valores que podem ser representados) reetem

    o tamanho \natural" do inteiro na m�aquina onde o programa ser�a executado. Usualmente, quatro

    bytes (32 bits) s~ao reservados para o tipo int nos computadores atuais, permitindo representar valores

    na faixa entre �231 a +231 � 1, ou �2 147 483 648 a 2 147 483 647.

    Os tipos oat e double representam valores reais, limitados apenas pela precis~ao da m�aquina

    que executa o programa. O tipo oat oferece cerca de seis d��gitos de precis~ao enquanto que double

    suporta o dobro da precis~ao de um oat.

    23 c1996

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    Alguns destes tipos b�asicos podem ser modi�cados por quali�cadores. Por exemplo, o tipo char

    pode ser acompanhado pelo quali�cador signed ou unsigned. O tipo signed char seria utilizado para

    indicar que a vari�avel do tipo char estaria representando pequenos n�umeros inteiros (na faixa de -128

    a 127). O tipo unsigned char seria utilizado para indicar que a vari�avel estaria armazenando valores

    inteiros exclusivamente positivos (sem sinal) na faixa de 0 a 255.

    O tipo int tamb�em pode ser quali�cado. Um tipo unsigned int indica que a vari�avel apenas

    armazenar�a valores positivos. Um tipo short int indica que (caso seja poss��vel) o compilador dever�a

    usar um n�umero menor de bytes para representar o valor num�erico | usualmente, dois bytes s~ao

    alocados para este tipo. Uma vari�avel do tipo long int indica que a representa�c~ao mais longa de um

    inteiro deve ser utilizada, sendo que usualmente quatro bytes s~ao reservados para vari�aveis deste

    tipo.

    Estas dimens~oes de vari�aveis denotam apenas uma situa�c~ao usual de�nida por boa parte dos

    compiladores, sendo que n~ao h�a nenhuma garantia quanto a isto. A �unica coisa que se pode a�rmar

    com rela�c~ao �a dimens~ao de inteiros em C �e que uma vari�avel do tipo short int n~ao ter�a um n�umero

    maior de bits em sua representa�c~ao do que uma vari�avel do tipo long int1.

    Em C, n�umeros inteiros podem ter representa�c~ao decimal, octal ou hexadecimal. N�umeros com

    representa�c~ao decimal s~ao denotados por qualquer sequência de algarismos entre 0 e 9 que inicie com

    um algarismo diferente de 0 | 10, 127, 512, etc. N�umeros em octal s~ao sequências de algarismos

    entre 0 e 7 iniciadas por 0 | 012 (decimal 10), 077 (decimal 63), etc. N�umeros em hexadecimal s~ao

    sequências de algarismos entre 0 e F iniciadas com o pre�xo 0x | 0xF (decimal 15), 0x1A (decimal

    26). As representa�c~oes octal e hexadecimal s~ao atrativas como formas compactas de representa�c~ao

    de valores bin�arios | cada algarismo da representa�c~ao octal pode ser diretamente expandido para

    uma sequência de três bits, e da representa�c~ao hexadecimal para sequências de quatro bits. Assim,

    tanto 127 quanto 0177 quanto 0x7F correspondem a uma mesma sequência de bits, 01111111.

    Valores com representa�c~ao em ponto utuante (reais) s~ao representados em C atrav�es do uso do

    ponto decimal, como em 1.5 para representar o valor um e meio. A nota�c~ao exponencial tamb�em

    pode ser usada, como em 1.2345e-6 ou em 0.12E3.

    Caracteres ASCII s~ao denotados entre aspas simples, tais como 'A'. Cada caracter ASCII corres-

    ponde tamb�em a uma representa�c~ao bin�aria usada internamente | por exemplo, o caracter ASCII

    A equivale a uma sequência de bits que corresponde ao valor hexadecimal 41H ou decimal 65. Os

    valores de�nidos para os caracteres ASCII s~ao apresentados no Apêndice C.

    1Estes quali�cadores reetem o estado atual do padr~ao ANSI-C. Dependendo do computador e do compiladordispon��vel, outros quali�cadores podem ser suportados, tais como long long e long double para representar inteirosde 64 bits e reais de precis~ao estendida (80 bits), respectivamente. Entretanto, n~ao h�a ainda nenhuma padroniza�c~aoneste sentido.

    DCA/FEEC/UNICAMP 24

  • Ricarte Declara�c~oes de Vari�aveis [2.3]

    Al�em dos caracteres alfanum�ericos e de pontua�c~ao, que podem ser representados em uma fun�c~ao

    diretamente pelo s��mbolo correspondente entre aspas, C tamb�em de�ne representa�c~oes para carac-

    teres especiais de controle do c�odigo ASCII atrav�es de sequências de escape iniciados pelo s��mbolo

    \ (contrabarra). As principais sequências s~ao:

    \n nova linha

    \t tabula�c~ao

    \b retrocesso

    \r retorno de carro

    \f alimenta�c~ao de formul�ario

    \\ contrabarra

    \' ap�ostrofo

    \" aspas

    \0 o caracter nul

    \xxx qualquer padr~ao de bits xxx em octal

    2.3 Declara�c~oes de Vari�aveis

    Vari�aveis representam uma forma de identi�car por um nome simb�olico uma regi~ao da mem�oria

    que armazena um valor sendo utilizado por uma fun�c~ao. Em C, uma vari�avel deve estar associada

    a um dos tipos de dados descritos na Se�c~ao 2.2.

    Toda vari�avel que for utilizada em uma fun�c~ao C deve ser previamente declarada. A forma geral

    de uma declara�c~ao de vari�avel �e:

    tipo nome_variavel;

    ou

    tipo nome_var1, nome_var2, ... ;

    onde nome var1, nome var2, : : : s~ao vari�aveis de um mesmo tipo de dado. Exemplos v�alidos de

    declara�c~ao de vari�aveis em C s~ao:

    int um_inteiro;

    unsigned int outro_inteiro;

    char c1, c2;

    float SalarioMedio;

    double x,

    y;

    25 c1996

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    Nomes de vari�aveis podem ser de qualquer tamanho, sendo que usualmente nomes signi�cativos

    devem ser utilizados. C faz distin�c~ao entre caracteres mai�usculos e caracteres min�usculos, de forma

    que Salariomedio �e diferente de SalarioMedio.

    H�a restri�c~oes aos nomes de vari�aveis. Palavras associadas a comandos e de�ni�c~oes da linguagem

    (tais como if, for e int) s~ao reservadas, n~ao podendo ser utilizadas para o nome de vari�aveis. A lista

    de palavras reservadas em C s~ao apresentadas no Apêndice A. O nome de uma vari�avel pode conter

    letras e n�umeros, mas deve come�car com uma letra.

    Como pode ser observado no exemplo acima, diversas vari�aveis de um mesmo tipo podem ser

    declaradas em um mesmo comando, sendo que o nome de cada vari�avel neste caso estaria separado

    por v��rgulas. Al�em disto, vari�aveis podem ser tamb�em inicializadas enquanto declaradas, como em

    int a = 0,

    b = 20;

    char c = 'X';

    long int d = 12345678L;

    Na �ultima linha deste exemplo (inicializa�c~ao da vari�avel d), o su�xo L indica que a constante �e do

    tipo long.

    Uma vari�avel cujo valor n~ao ser�a alterado pelo programa pode ser quali�cada como const, como

    em

    const int NotaMaxima = 100;

    Neste caso, a vari�avel NotaMaxima n~ao poder�a ter seu valor alterado. Evidentemente, vari�aveis deste

    tipo devem ser inicializadas no momento de sua declara�c~ao.

    2.4 Express~oes

    Ap�os a declara�c~ao das vari�aveis, o corpo de uma fun�c~ao �e de�nido atrav�es dos comandos que

    ser~ao executados pela fun�c~ao. Estes comandos devem ser expressos sob a forma de uma sequência

    de express~oes v�alidas da linguagem C.

    Antes de mais nada, �e interessante que se apresente a forma de se expressar coment�arios em

    um programa C. Coment�arios em C s~ao indicados pelos terminadores /* (in��cio de coment�ario)

    e */ (�m de coment�ario). Quaisquer caracteres entre estes dois pares de s��mbolos s~ao ignorados

    pelo compilador. Coment�arios em C n~ao podem ser aninhados, mas podem se estender por diversas

    linhas e podem come�car em qualquer coluna. Por exemplo,

    DCA/FEEC/UNICAMP 26

  • Ricarte Express~oes [2.4]

    /* Exemplo de

    * comentario

    */

    main( ) {

    /* esta funcao nao faz coisa alguma */

    }

    As express~oes na linguagem C s~ao sempre terminadas pelo s��mbolo ; (ponto e v��rgula). Uma

    express~ao nula �e constitu��da simplesmente pelo s��mbolo terminador. Assim, o exemplo acima �e

    equivalente a

    /* Exemplo de

    * comentario

    */

    main( ) {

    /* esta funcao nao faz coisa alguma */

    ;

    }

    2.4.1 Express~oes Aritm�eticas

    O comando de atribui�c~ao em C �e indicado pelo s��mbolo =, como em

    main() {

    int a, b, c;

    a = 10; /* a recebe valor 10 */

    b = c = a; /* b e c recebem o valor de a (10) */

    }

    Observe neste exemplo que a atribui�c~ao pode ser encadeada | na �ultima linha da fun�c~ao acima, c

    recebe inicialmente o valor da vari�avel a, e ent~ao o valor de c ser�a atribu��do �a vari�avel b.

    Express~oes aritm�eticas em C podem envolver os operadores bin�arios (isto �e, operadores que

    tomamdois argumentos) de soma (+), subtra�c~ao (-),multiplica�c~ao (*), divis~ao (/). Valores negativos

    s~ao indicados pelo operador un�ario -. Adicionalmente, para opera�c~oes envolvendo valores inteiros

    s~ao de�nidos os operadores de resto da divis~ao inteira ou m�odulo (%), incremento (++) e decremento

    (--). Por exemplo,

    27 c1996

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    main() {

    int a=10, b, c, d;

    b = 2*a; /* b = 20 */

    a++; /* a = a+1 (11) */

    c = b/a; /* divisao inteira: c = 1 */

    d = b%a; /* resto da divisao: d = 9 */

    }

    Cada um dos operadores de incremento e decremento tem duas formas de uso, dependendo se

    eles ocorrem antes do nome da vari�avel (pr�e-incremento ou pr�e-decremento) ou depois do nome

    da vari�avel (p�os-incremento ou p�os-decremento). No caso do exemplo acima, onde o operador de

    incremento ocorre de forma isolada em uma express~ao (sozinho na linha), as duas formas poss��veis

    s~ao equivalentes. A diferen�ca entre eles ocorre quando estes operadores s~ao combinados com outras

    opera�c~oes. No exemplo acima, as linhas de atribui�c~ao �a b e incremento de a poderiam ser combinados

    em uma �unica express~ao,

    b = 2*(a++); /* b recebe 2*a e entao a recebe a+1 */

    Observe como esta express~ao �e diferente de

    b = 2*(++a); /* a recebe a+1 e entao b recebe 2*a */

    Na pr�atica, os parênteses nas duas express~oes acima poderiam ser omitidos uma vez que a pre-

    cedência do operador de incremento �e maior que da multiplica�c~ao | ou seja, o incremento ser�a

    avaliado primeiro. O Apêndice B apresenta a ordem de avalia�c~ao para todos os operadores da

    linguagem C.

    C tem tamb�em uma forma compacta de representar express~oes na forma

    var = var op (expr);

    onde uma mesma vari�avel var aparece nos dois lados de um comando de atribui�c~ao. A forma

    compacta �e

    var op= expr;

    Por exemplo,

    a += b; /* equivale a a = a+b */

    c *= 2; /* equivale a c = c*2 */

    DCA/FEEC/UNICAMP 28

  • Ricarte Express~oes [2.4]

    2.4.2 Express~oes Condicionais

    Um tipo muito importante de express~ao em C �e a express~ao condicional, cujo resultado �e um

    valor que ser�a interpretado como falso ou verdadeiro. Como a linguagem C n~ao suporta diretamente

    o tipo de dado booleano, ela trabalha com representa�c~oes inteiras para denotar estes valores | o

    resultado de uma express~ao condicional �e um valor inteiro que ser�a interpretado como falso quando

    o valor resultante da express~ao �e igual a 0, e como verdadeiro quando o valor resultante �e diferente

    de 0.

    Assim, qualquer express~ao inteira pode ser interpretada como uma express~ao condicional. A

    situa�c~ao mais comum, entretanto, �e ter uma express~ao condicional comparando valores atrav�es dos

    operadores relacionais. Os operadores relacionais em C s~ao:

    > maior que

    >= maior que ou igual a

    < menor que

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    parênteses em express~oes para tornar claro quais opera�c~oes s~ao desejadas. A exce�c~ao a esta regra

    ocorre quando um n�umero excessivo de parênteses pode di�cultar ainda mais a compreens~ao da

    express~ao; em tais casos, o uso das regras de precedência da linguagem pode facilitar o entedimento

    da express~ao.

    2.4.3 Operadores de Bits

    A linguagem C oferece tamb�em operadores que trabalham sobre a representa�c~ao bin�aria de

    valores inteiros e caracteres. Estes operadores s~ao:

    & AND bit-a-bit

    | OR bit-a-bit

    ^ XOR bit-a-bit

    > deslocamento de bits �a direita

    ~ complemento de um (inverte cada bit)

    Estes operadores tomam dois argumentos exceto pelo operador ~, que �e un�ario. Por exemplo,

    a = x & 0177; /* a recebe 7 bits menos signif. de x */

    b &= ~0xFF; /* zera os 8 bits menos signif. de b */

    c >>= 4; /* desloca represent. de c 4 bits a direita */

    2.5 Controle do Fluxo de Execu�c~ao

    C �e uma linguagem que suporta a programa�c~ao estruturada, ou seja, permite agrupar comandos

    na forma de sequência, sele�c~ao e repeti�c~ao.

    Uma sequência de comandos em uma fun�c~ao C �e denotada simplesmente como uma sequência

    de express~oes, como exempli�cado na Figura 2.3. H�a duas possibilidades: usar comandos isolados

    (a forma mais utilizada) ou usar uma �unica express~ao com a sequência de comandos separados pelo

    operador , (v��rgula).

    A constru�c~ao de sele�c~ao IF-THEN-ELSE �e expressa em C na forma if: : : else (Figura 2.4). Ap�os a

    palavra-chave if deve haver uma express~ao condicional entre parênteses. Se a express~ao for avaliada

    como verdadeira, ent~ao a express~ao sob if ser�a realizada; se for falsa, a express~ao sob else ser�a

    executada.

    Nesta �gura, introduz-se o conceito de express~ao composta, ou seja, a express~ao da parte else

    deste exemplo �e na verdade um bloco contendo diversas express~oes. Neste caso, o bloco de comandos

    DCA/FEEC/UNICAMP 30

  • Ricarte Controle do Fluxo de Execu�c~ao [2.5]

    a = 10

    b = a*5

    c = a+b

    a = 10;

    b = a*5;

    c = a+b;

    (a) (b)

    ou

    a=10, b=a*5, c=a+b;

    Figura 2.3: Sequência em C: (a) uxograma; (b) formas equivalentes em C.

    que deve ser executado nesta condi�c~ao deve ser delimitado por chaves f e g. Algumas observa�c~oes

    adicionais relevantes com rela�c~ao a este comando s~ao:

    1. Em C, h�a diferen�cas entre letras min�usculas e mai�usculas. Como todos os comandos em C,

    as palavras chaves deste comando est~ao em letras min�usculas. Assim, as formas IF (ou If ou

    iF ) n~ao s~ao formas v�alidas em C para denotar o comando if.

    2. Ao contr�ario do que ocorre em Pascal ou FORTRAN, a palavra then n~ao faz parte da sintaxe

    deste comando em C.

    3. A cl�ausula else pode ser omitida quando a express~ao a executar na condi�c~ao falsa for nula.

    4. No caso de haver mais de um if que possa ser associado a uma cl�ausula else, esta ser�a associada

    ao comando if precedente mais pr�oximo.

    A constru�c~ao estruturada de sele�c~ao CASE-SELECT �e suportada em C pelo comando switch: : : case

    (Figura 2.5). Neste caso, ap�os a palavra-chave switch deve haver uma vari�avel do tipo inteiro ou

    caracter entre parênteses. Ap�os a vari�avel, deve haver uma lista de casos que devem ser considerados,

    cada caso iniciando com a palavra-chave case seguida por um valor ou uma express~ao inteira.

    31 c1996

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    c = a*10

    b = b+a

    a = 10?

    (a) (b)

    if (a == 10)

    else {

    c = a*10;

    b = b+a;

    }

    b = b-c

    b = b-c;

    T F

    Figura 2.4: Sele�c~ao com if: : : else em C: (a) uxograma; (b) equivalente em C.

    DCA/FEEC/UNICAMP 32

  • Ricarte Controle do Fluxo de Execu�c~ao [2.5]

    a = 10? a = a+1

    a = a+10

    a = 100? a = a+5

    a = 20? a = a+2

    T

    T

    T

    F

    F

    F switch (a) { case 10: a = a+1;

    break;

    case 20: a = a+2;

    break;

    case 100: a = a+5;

    break;

    default: a = a+10;

    }

    (a) (b)

    Figura 2.5: Sele�c~ao em C usando a forma switch: : :case. Observe que o conjunto de a�c~oes associadoa cada caso encerra-se com a palavra-chave break.

    33 c1996

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    Neste exemplo, a vari�avel a pode ser do tipo int ou char. A palavra-chave especial default indica

    que a�c~ao deve ser tomada quando a vari�avel assume um valor que n~ao foi previsto em nenhum dos

    casos. Assim como a condi�c~ao else no comando if �e opcional, a condi�c~ao default tamb�em �e opcional

    para o switch-case. Observe tamb�em a importância da palavra-chave break para delimitar o escopo

    de a�c~ao de cada caso | fossem omitidas as ocorrências de break no exemplo, a semântica associada

    ao comando seria essencialmente diferente (Figura 2.6).

    a = 10? a = a+1

    a = a+10

    a = 100? a = a+5

    a = 20? a = a+2

    T

    T

    T

    F

    F

    F switch (a) { case 10: a = a+1;

    (a) (b)

    case 20: a = a+2;

    case 100: a = a+5;

    default: a = a+10;

    }

    Figura 2.6: Sele�c~ao em C usando a forma switch: : : case onde se omitiu a palavra-chave break dobloco de comandos.

    Comandos de repeti�c~ao em C s~ao suportados em três formas distintas. A primeira forma �e while,

    cuja constru�c~ao equivale ao comando estruturado WHILE-DO (Figura 2.7(a) e (b)), enquanto que a

    DCA/FEEC/UNICAMP 34

  • Ricarte Invoca�c~ao de Fun�c~oes [2.6]

    segunda forma equivale ao comando estruturado DO-WHILE (Figura 2.7(c) e (d)).

    A terceira forma associada ao comando de repeti�c~ao em C, for, facilita a express~ao de itera�c~oes

    associadas a contadores. Um exemplo de uso deste comando �e apresentado na Figura 2.8.

    Neste exemplo, a �e uma vari�avel que tem a fun�c~ao de contador, assumindo valores 0, 1, : : : ,

    MAX-1. Enquanto o valor de a for menor que MAX (a condi�c~ao de t�ermino da itera�c~ao), a express~ao

    (simples ou composta) no corpo da itera�c~ao ser�a repetidamente avaliada.

    Qualquer que seja forma usada para indicar o comando de repeti�c~ao | while, do: : :while ou

    for | h�a duas formas de se desviar a sequência de execu�c~ao do padr~ao do comando. A primeira

    forma, continue, serve para indicar o �m prematuro de uma itera�c~ao. A outra forma de interrup�c~ao

    de um comando de repeti�c~ao �e o comando break, que indica o �m prematuro de todo o comando de

    itera�c~ao. Por exemplo, em

    for (a=0; a

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    a = a+1 while (a != 10) a = a+1;

    a = a+1

    T

    F

    a != 10?

    (a) (b)

    a != 10?T

    F

    do

    a = a+1;

    while (a != 10);

    (c)

    (d)

    Figura 2.7: Repeti�c~ao em C: (a) forma while; (b) forma do: : :while

    DCA/FEEC/UNICAMP 36

  • Ricarte Invoca�c~ao de Fun�c~oes [2.6]

    for (a=0; a

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    Uma fun�c~ao agrupa sob um nome simb�olico um conjunto de express~oes que realizam uma a�c~ao

    que, potencialmente, pode se repetir diversas vezes. Por exemplo, considere uma aplica�c~ao em

    instrumenta�c~ao onde os 8 bits menos signi�cativos de uma vari�avel inteira devem ser frequentemente

    lidos. Seria poss��vel fazer uma fun�c~ao associada �a leitura de cada bit, como em

    int get_bit1 (int var) {

    return (var & 01);

    }

    int get_bit2 (int var) {

    return ((var & 02) >> 1);

    }

    ...

    int get_bit8 (int var) {

    return ((var & 0200) >> 7);

    }

    o que j�a auxiliaria no sentido de evitar a repeti�c~ao das opera�c~oes de manipula�c~ao de bits, reduzindo

    assim a possibilidade de erro e facilitando o entendimento do c�odigo. Estas fun�c~oes poderiam estar

    sendo utilizadas pela aplica�c~ao como em

    main() {

    int leitura, bit; /* declaracao de variavel */

    int faz_medida(void), /* declaracao de funcoes */

    get_bit1(int),

    get_bit2(int),

    ...

    get_bit8(int);

    do {

    leitura = faz_medida(); /* alguma funcao de medida */

    bit = get_bit1(leitura);

    ... /* trata o bit 1 */

    bit = get_bit2(leitura);

    DCA/FEEC/UNICAMP 38

  • Ricarte Invoca�c~ao de Fun�c~oes [2.6]

    ... /* trata o bit 2 */

    ...

    } while (1);

    }

    Este exemplo ilustra alguns pontos interessantes. O primeiro deles �e a declara�c~ao de fun�c~oes, onde

    se expressa quais fun�c~oes ser~ao utilizadas, quais os tipos de seus argumentos e quais os seus valores

    de retorno. Um dos \tipos" indicados �e void, o que signi�ca vazio | ou seja, a fun�c~ao faz medida

    deste exemplo n~ao toma nenhum argumento e retorna um valor inteiro.

    Outro ponto interessante �e o uso da forma while(1), o que equivale a dizer \fa�ca para sempre."

    Esta forma �e frequentemente utilizada, sendo em geral interrompida por um comando break. Usando

    o comando for, a forma equivalente seria for(;;).

    Outra observa�c~ao que deve ser feita �e que o valor da vari�avel leitura n~ao se altera com as

    chamadas das diversas fun�c~oes. Esta �e uma caracter��stica da passagem por valor dos argumentos da

    fun�c~ao, que �e o padr~ao em C. O que cada fun�c~ao manipula | cada vari�avel var | �e na verdade

    uma c�opia do valor da vari�avel passada como argumento (leitura), e n~ao diretamente a vari�avel.

    2.6.1 A Fun�c~ao printf

    A fun�c~ao printf �e parte de um conjunto de fun�c~oes pr�e-de�nidas armazenadas em uma biblioteca

    padr~ao de rotinas da linguagem C. Ela permite apresentar na tela os valores de qualquer tipo de

    dado. Para tanto, printf utiliza o mecanismo de formata�c~ao, que permite traduzir a representa�c~ao

    interna de vari�aveis para a representa�c~ao ASCII que pode ser apresentada na tela.

    O primeiro argumento de printf �e um string de controle, uma sequência de caracteres entre aspas.

    Esta string, que sempre deve estar presente, pode especi�car atrav�es de caracteres especiais (as

    sequências de convers~ao) quantos outros argumentos estar~ao presentes nesta invoca�c~ao da fun�c~ao.

    Estes outros argumentos ser~ao vari�aveis cujos valores ser~ao formatados e apresentados na tela. Por

    exemplo, se o valor de uma vari�avel inteira x �e 12, ent~ao a execu�c~ao da fun�c~ao

    printf("Valor de x = %d", x);

    imprime na tela a frase Valor de x = 12. Se y �e uma vari�avel do tipo caracter com valor 'A', ent~ao

    a execu�c~ao de

    printf("x = %d e y = %c\n", x, y);

    39 c1996

  • Princ��pios de Programa�c~ao C Programa�c~ao C

    imprime na tela a frase x = 12 e y = A seguida pelo caracter de nova linha (\n), ou seja, a pr�oxima

    sa��da para a tela aconteceria na linha seguinte. Observe que a sequência de convers~ao pode ocorrer

    dentro de qualquer posi�c~ao dentro do string de controle.

    A fun�c~ao printf n~ao tem um n�umero �xo de argumentos. Em sua forma mais simples, pelo menos

    um argumento deve estar presente | a string de controle. Uma string de controle sem nenhuma

    sequência de convers~ao ser�a literalmente impressa na tela. Com vari�aveis adicionais, a �unica forma

    de saber qual o n�umero de vari�aveis que ser�a apresentado �e por inspe�c~ao da string de controle. Desta

    forma, cuidado deve ser tomado para que o n�umero de vari�aveis ap�os a string de controle esteja de

    acordo com o n�umero de sequências de convers~ao presente na string de controle.

    Al�em de ter o n�umero correto de argumentos e sequências de convers~ao, o tipo de cada vari�avel

    deve estar de acordo com a sequência de convers~ao especi�cada na string de controle. A sequência

    de convers~ao pode ser reconhecida dentro da string de controle por iniciar sempre com o caracter %.

    As principais sequências de convers~ao para vari�aveis caracteres e inteiras s~ao:

    %c imprime o conte�udo da vari�avel com representa�c~ao ASCII;

    %d imprime o conte�udo da vari�avel com representa�c~ao decimal com sinal;

    %u imprime o conte�udo da vari�avel com representa�c~ao decimal sem sinal;

    %o imprime o conte�udo da vari�avel com representa�c~ao octal sem sinal;

    %x imprime o conte�udo da vari�avel com representa�c~ao hexadecimal sem sinal.

    Uma largura de campo pode ser opcionalmente especi�cada logo ap�os o caracter %, como em %12d

    para especi�car que o n�umero decimal ter�a reservado um espa�co de doze caracteres para sua repre-

    senta�c~ao. Se a largura de campo for negativa, ent~ao o n�umero ser�a apresentado alinhado �a esquerda

    ao inv�es do comportamento padr~ao de alinhamento �a direita. Para a convers~ao de vari�aveis do tipo

    long, o caracter l tamb�em deve ser especi�cado, como em %ld.

    Para converter vari�aveis em ponto utuante, as sequências s~ao:

    %f imprime o conte�udo da vari�avel com representa�c~ao com ponto decimal;

    %e imprime o conte�udo da vari�avel com representa�c~ao em nota�c~ao cient���ca (exponencial);

    %g formato geral, escolhe a representa�c~ao mais curta entre %f e %e.

    Como para a representa�c~ao inteira, uma largura de campo pode ser especi�cada para n�umeros reais.

    Por exemplo, %12.3f especi�ca que a vari�avel ser�a apresentada em um campo de doze caracteres

    com uma precis~ao de três d��gitos ap�os o ponto decimal.

    DCA/FEEC/UNICAMP 40

  • Ricarte Atividades [2.7]

    Finalmente, se a vari�avel a ser apresentada �e uma sequência de caracteres (um string), ent~ao o

    formato de convers~ao %s pode ser utilizado. Para apresentar o caracter %, a sequência %% �e utilizada.

    2.7 Atividades

    Atividade 1 Crie um programa C que imprima na tela a mensagem

    ``C ou nao C, eis a questao!''

    Edite e compile o arquivo ser.c contendo este programa, criando um execut�avel de

    nome ser.

    Atividade 2 Analise as mensagens de erro que o compilador C ir�a apresentar para cada uma das

    seguintes situa�c~oes:

    (a) tentar gerar um programa execut�avel sem uma fun�c~ao main;

    (b) incluir uma express~ao dentro de uma fun�c~ao onde o terminador ; tenha sido

    omitido;

    (c) tentar alterar uma vari�avel declarada como const;

    (d) usar uma vari�avel que n~ao foi declarada;

    (e) declarar uma vari�avel que n~ao �e usada;

    (f) a express~ao y = x;, onde x e y s~ao de um mesmo tipo, ocorre sem que o valor de

    x tenha sido de�nido;

    (g) a express~ao y = x; ocorre, por�em x �e uma vari�avel do tipo oat enquanto que y �e

    do tipo char;

    (h) uma vari�avel �e declarada com um nome inv�alido;

    (i) um bloco em um dos comandos de controle estruturado n~ao foi apropriadamente

    encer