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...
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