Você está na página 1de 70

Captulo

3
113
INTRODUO LINGUAGEM C
3.1 A Linguagem C
A linguagem C foi desenvolvida no incio da dcada de 1970 num laboratrio da AT&T
por Dennis Ritchie como uma linguagem de alto nvel dispondo de facilidades de bai-
xo nvel, de modo que fosse possvel contemplar satisfatoriamente todas as qualidades
desejveis de um bom programa (v. Seo 1.3).
Com o ganho de popularidade a partir dos anos 1980, a linguagem C passou a
contar com vrios compiladores que apresentavam caractersticas diferentes daquelas
que faziam parte da especifcao original da linguagem. Essas discrepncias comprome-
tiam uma das principais caractersticas desejveis em programas escritos em linguagens
de alto nvel: a portabilidade. Para que houvesse compatibilidade entre compiladores,
foi necessrio criar uma padronizao da linguagem que fosse seguida pelos fabrican-
tes de compiladores.
A padronizao da linguagem C foi inicialmente realizada por um comit do
American National Standards Institute (ANSI) em 1989 e, por causa disso, foi deno-
minada de ANSI C. Posteriormente, essa padronizao passou a ser conhecida como
C89. Em 1990, um comit ISO assumiu a responsabilidade pela padronizao de C e
aprovou o padro ANSI. Popularmente, esse padro denominado C90, que , essen-
cialmente, o mesmo padro C89. Em 1999, o comit ISO responsvel pela padroni-
zao de C aprovou o padro de C popularmente conhecido como C99 e, fnalmente,
em dezembro de 2011, ratifcou o mais recente padro da linguagem, conhecido co-
mo C11. Entretanto, at o fnal da escrita deste livro, este ltimo padro ainda recebia
pouco suporte por parte dos fabricantes de compiladores.
Apesar de muitos fabricantes de compiladores de C desenvolverem suas prprias
verses dessa linguagem, eles oferecem a opo ANSI C (ou ISO C) que pode ser es-
colhida pelo programador, por exemplo, por meio de uma opo de compilao. Em
nome da portabilidade, sempre recomendvel utilizar uma opo ANSI/ISO C (v.
Seo 1.7.2).
No obstante todos os esforos de padronizao, muitas construes da linguagem
C ainda tm interpretaes que variam de compilador para compilador. Isso ocorre
em virtude de ambiguidades e omisses ora na defnio original da linguagem ora em
antigas verses de padronizao. Esses problemas, apesar de reconhecidos, so perpetu-
ados a cada novo padro para garantir compatibilidade histrica; isto , para garantir
114 | Captulo 3 Introduo Linguagem C
que programas antigos continuem podendo ser compilados num padro mais recente.
Ao longo do texto, cada caracterstica de C que pode ter mais de uma interpretao
identifcada como dependente de implementao. Esse termo mais preciso do que
dependente de compilador, pois diferentes verses (i.e., implementaes de C) de um
mesmo compilador podem ter interpretaes diferentes para uma dada construo da
linguagem.
3.2 Identifcadores
Um identifcador serve para nomear componentes utilizados num programa escrito
numa dada linguagem de programao.
3.2.1 Regras para Criao de Identifcadores
Cada linguagem de programao possui regras prprias para formao de seus identi-
fcadores. As regras para criao de identifcadores em C so as seguintes:
Caracteres permitidos. Um identifcador em C deve ser constitudo apenas
de letras, dgitos e _ (subtrao). Aqui, letra no inclui, por exemplo, ou ca-
racteres acentuados de Portugus.
Restrio. O primeiro caractere de um identifcador no pode ser um dgito.
Tamanho. O nmero de caracteres permitido num identifcador depende da
verso do padro de C utilizada. O padro ISO C90 requer que compilado-
res de C aceitem, pelo menos, 31 caracteres; nos padres mais recentes (C99
e C11), esse nmero passou a ser 63. Normalmente, compiladores modernos
do liberdade para programadores sensatos escreverem identifcadores do ta-
manho desejado, de modo que no necessrio memorizar esses nmeros.
Uma caracterstica importante da linguagem C que ela, diferentemente de algu-
mas outras linguagens (p. ex., Pascal), faz distino entre letras maisculas e minsculas.
Por exemplo, as variveis denominadas umaVar e UmaVar so consideradas diferentes.
3.2.2 Palavras-chaves
Palavras que possuem signifcado especial numa linguagem de programao (p. ex.,
while e for em C) so denominadas palavras-chaves da linguagem. Essas palavras no
podem ser redefnidas pelo programador. Por exemplo, no permitido ter uma vari-
vel denominada while em C.
3.2.3 Palavras Reservadas
Identifcadores disponibilizados pela biblioteca padro de C (v. Seo 3.13) so conhe-
cidos como palavras reservadas (p. ex., printf) e o programador deve evitar redefni-los
em seus programas. Identifcadores que comeam por subtrao tambm so reservados
pela linguagem C e, portanto, tambm devem ser evitados.
3.3 Cdigos de Caracteres
Os caracteres que devem fazer parte de uma implementao de C so denominados
coletivamente conjunto bsico de caracteres. Cada conjunto bsico de caracteres de-
ve conter um subconjunto mnimo de 96 caracteres especifcado pelo padro de C e o
Tipos de Dados Primitivos | 115
valor inteiro atribudo a cada caractere deve caber em um byte. Devem fazer parte do
conjunto bsico de caracteres os caracteres que aparecem na Tabela 31.
CATEGORIA CARACTERES
Letras Maisculas
A B C D E F G H I J K L M N O P Q R S T U V W
X Y Z
Letras Minsculas
a b c d e f g h i j k l m n o p q r s t u v w
x y z
Dgitos
0 1 2 3 4 5 6 7 8 9
Caracteres Grfcos
! " # % & ' ( ) * + , - . / : ; < = > ? [ \ ]
^ _ { | } ~
Espaos em Branco
espao (' '), tabulao horizontal ('\t'), tabulao vertical
('\v'), quebra de linha ('\n') e quebra de pgina ('\f')
TABELA 31: CONJUNTO BSICO DE CARACTERES DE C
Um cdigo de caracteres consiste num mapeamento entre um conjunto de ca-
racteres e um conjunto de inteiros. Como exemplos de cdigo de caracteres bem co-
nhecidos tm-se: ASCII, EBCDIC e ISO 8859-1.
O cdigo ASCII um dos mais antigos e conhecidos cdigos de caracteres. Esse
cdigo de caracteres usa apenas 7 bits (e no 8 como muitos pensam), de modo que o
nmero total de caracteres no cdigo ASCII original 128 (i.e., 2
7
) e eles so mapea-
dos em inteiros no intervalo de 0 a 127.
Outro antigo cdigo de caracteres EBCDIC, que contm todos os caracteres que
constam no cdigo ASCII. Porm, os mapeamentos desses dois cdigos de caracteres
no so equivalentes. Alm disso, os valores inteiros que mapeiam as letras do cdigo
EBCDIC no so consecutivos. Por exemplo, os valores inteiros associados s letras i e
j no cdigo EBCDIC so, respectivamente, 137 e 145. No cdigo ASCII, essas mesmas
letras so representadas por 105 e 106, respectivamente.
Apesar de o padro ISO de C no especifcar um cdigo de caracteres que deva
ser usado com a linguagem, a maioria dos cdigos de caracteres em uso atualmente
em implementaes de C pode ser considerada extenso do cdigo ASCII. Ou seja,
os cdigos de caracteres mais usados correntemente preservam os caracteres do cdigo
ASCII e seus mapeamentos. Exemplos de tais cdigos de caracteres so aqueles espe-
cifcados pelo padro ISO 8859.
Em resumo, como nenhum padro de C requer o uso de qualquer cdigo de ca-
racteres especfco, o programador jamais deve fazer qualquer suposio sobre o cdigo
de caracteres utilizado por uma dada implementao de C.
3.4 Tipos de Dados Primitivos
Um tipo de dado consiste de um conjunto de valores munido de uma coleo de ope-
raes permitidas sobre eles. Um tipo primitivo (ou embutido) um tipo incorporado
numa linguagem de programao e representado por uma palavra-chave. A linguagem
C oferece ainda a possibilidade de criao de inmeros outros tipos. Esses tipos, deno-
minados tipos derivados, podem ser criados pelo prprio programador (v. Seo 9.2)
ou providos pela biblioteca padro de C (v. Seo 3.13).
116 | Captulo 3 Introduo Linguagem C
Existem muitos tipos de dados primitivos em C, mas, em virtude da natureza intro-
dutria deste livro, apenas dois tipos inteiros (int e char) e um real (double) sero
discutidos aqui.
3.4.1 int
Existem diversos tipos inteiros primitivos em C. Neste livro, o tipo int foi escolhido
para representar essa categoria porque ele o tipo inteiro mais largamente usado e,
principalmente, porque fcil de lembrar (i.e., int corresponde s trs primeiras letras
de inteiro). O tipo int, por outro lado, herda um grave defeito desde os primrdios da
criao da linguagem C: sua largura (i.e., o nmero de bytes ocupados por um valor
desse tipo) no precisamente especifcada. Portanto, esse tipo pode ser usado sem
problemas com objetivos didticos (como o caso aqui), mas nunca deve ser usado
na prtica.
3.4.2 char
O espao ocupado em memria por valores do tipo char sempre um byte. Esse tipo
comumente usado para representar caracteres, mas pode tambm representar inteiros
que requerem apenas um byte de memria. Isto , uma varivel do tipo char pode re-
presentar tanto um caractere quanto um inteiro que no est associado a um caractere,
desde que esse inteiro caiba em um byte. Neste livro, esse tipo ser usado apenas em
processamento de caracteres.
3.4.3 double
Existem trs tipos reais em C, mas, neste livro introdutrio, apenas o tipo double ser
utilizado.
importante salientar que, assim como alguns nmeros reais no podem ser exa-
tamente representados em base decimal (p. ex., 1/3), o mesmo ocorre com represen-
tao na base binria, que usada por computadores para representar nmeros reais.
Portanto, muitos valores reais que possuem representao decimal exata em base decimal
so representados de modo aproximado em base binria. Por exemplo, o valor 0.1 pode
ser representado exatamente em base decimal, mas esse no o caso em base binria.
3.5 Constantes
Existem cinco tipos de constantes em C: inteiras, reais, caracteres, strings e de enu-
meraes. Constantes desse ltimo tipo sero vistas no Captulo 9, enquanto que as
demais sero apresentadas a seguir.
3.5.1 Constantes Inteiras
Constantes inteiras em C podem ser classifcadas de acordo com a base numrica utili-
zada em: decimais, octais e hexadecimais. Em programao de alto nvel, apenas cons-
tantes em base decimal so usadas. Por isso, este livro s usa constantes dessa categoria.
Constantes inteiras em base decimal so escritas utilizando-se os dgitos de 0 a
9, sendo que o primeiro dgito no pode ser zero, a no ser quando o prprio valor
zero. Exemplos vlidos de constantes inteiras decimais so: 0, 12004, -67. Um exem-
plo invlido seria 06, pois o nmero comea com zero e seria interpretado como uma
constante na base octal.
Constantes | 117
3.5.2 Constantes Reais
Constantes reais podem ser escritas em duas notaes:
Notao convencional. Nessa notao, um ponto decimal separa as partes
inteira e fracionria do nmero, como, por exemplo:
3.1415
.5 [a parte inteira zero]
7. [a parte fracionria zero]
Notao cientfca. Nessa notao, um nmero real consiste de duas partes:
(1) mantissa e (2) expoente. Essas partes so separadas por e ou E e a segun-
da parte representa uma potncia de 10. Por exemplo, o nmero 2E4 deve ser
interpretado como 210
4
e lido como dois vezes dez elevado quarta potncia.
A mantissa de um nmero real pode ser inteira ou decimal, enquanto que o
expoente pode ser positivo ou negativo, mas deve ser inteiro. Por exemplo,
2.5E-3 representa o nmero 2.510
-3
; ou seja, 0.0025.
3.5.3 Caracteres Constantes
Existem duas formas bsicas de representao de caracteres constantes em C:
Escrevendo-se o caractere entre apstrofos (p. ex., 'A'). Apesar de essa for-
ma de representao ser a mais legvel e portvel, ela factvel apenas quando
o caractere possui representao grfca e o programador possui meios para
introduzi-lo (p. ex., uma confgurao adequada de teclado).
Por meio de uma sequncia de escape, que consiste do caractere \ (barra in-
vertida) seguido por um caractere com signifcado especial, sendo ambos envol-
vidos entre apstrofos. Sequncias de escape devem ser usadas para representar
certos caracteres que no possuem representao grfca (p. ex., quebra de li-
nha) ou que tm signifcados especiais em C (p. ex., apstrofo). Essa forma de
representao de caracteres tambm portvel, apesar de ser menos legvel do
que a forma de representao anterior. A Tabela 32 apresenta as sequncias
de escape mais comuns que podem ser utilizadas num programa escrito em C.
SEQUNCIA DE ESCAPE DESCRIO FREQUNCIA DE USO
'\a'
Campainha (alerta) Raramente usada
'\t'
Tabulao Frequentemente usada
'\n'
Quebra de linha Muito usada
'\r'
Retorno (incio da linha) Raramente usada
'\b'
Retrocede um caractere Raramente usada
'\0'
Caractere nulo Muito usada
'\\'
Barra invertida Eventualmente usada
'\''
Apstrofo Eventualmente usada
'\"'
Aspas Eventualmente usada
TABELA 32: SEQUNCIAS DE ESCAPE E SEUS SIGNIFICADOS
As sequncias de escape '\t' e '\n' so usadas com muita frequncia em forma-
tao de dados na tela usando printf() (v. Seo 3.14.1). Em instrues de sada na
tela, '\r' faz o cursor mover-se para o incio da linha corrente, enquanto que '\b'
118 | Captulo 3 Introduo Linguagem C
faz o cursor mover-se uma posio para trs. A sequncia de escape '\0' usada em
processamento de strings (v. Captulo 8).
importante salientar que um caractere constante pode ser representado tanto
em um dos formatos descritos quanto por um nmero inteiro capaz de ser contido em
um byte. Isto , uma constante composta de um caractere ou uma sequncia de escape
entre apstrofos apenas informa o compilador que ele deve considerar o valor corres-
pondente ao caractere ou sequncia de escape no cdigo de caracteres que ele usa. Por
exemplo, se o cdigo de caracteres utilizado for ASCII, quando o compilador encontra
a constante 'A', ele a interpreta como 65 (esse valor corresponde ao mapeamento do
caractere A no cdigo ASCII).
Em resumo, qualquer que seja o formato de caractere constante utilizado, o com-
pilador interpreta-o como o valor inteiro correspondente ao caractere no cdigo de
caracteres utilizado na respectiva implementao de C. Entretanto, no uma boa
ideia representar caracteres num programa por constantes inteiras por duas razes. A
primeira razo legibilidade (por exemplo, ser que algum vai entender o que signifca
65 quando ler seu programa?). Requerer que algum use uma tabela de caracteres para
entender seu programa no sensato. A segunda razo que o programa pode ter sua
portabilidade comprometida, pois o padro de C no especifca que o cdigo de carac-
teres utilizado por um compilador deva ser ASCII ou qualquer outro (v. Seo 3.3).
3.5.4 Strings Constantes
Um string constante consiste de uma sequncia de caracteres constantes. Em C, um
string constante pode conter caracteres constantes em qualquer dos formatos apresen-
tados e deve ser envolvido entre aspas. Exemplos de strings constantes so:
"bola"
"Dia\tMes\tAno\n"
Strings constantes separados por um ou mais espaos em branco (incluindo tabu-
lao horizontal e quebra de linha) so automaticamente concatenados pelo compila-
dor. Isso til quando se tem um string constante muito grande e deseja-se escrev-lo
em duas linhas. Por exemplo:
"Este e' um string constante muito grande para "
"ser contido numa unica linha do meu programa"
Os dois strings constantes do ltimo exemplo sero concatenados pelo compilador
para formar um nico string constante:
"Este e' um string constante muito grande para ser contido numa
unica linha do meu programa"
3.6 Propriedades dos Operadores da Linguagem C
Informalmente, um operador representa uma operao elementar da linguagem C. Essa
operao , dependendo dela, aplicada a um ou mais valores denominados operandos.
C uma linguagem intensivamente baseada no uso de operadores. Portanto, o
entendimento das propriedades dos operadores da linguagem fundamental para a
aprendizagem da prpria linguagem.
As propriedades dos operadores so divididas em duas categorias:
Propriedades dos Operadores da Linguagem C | 119
1. Propriedades que todos os operadores possuem. Essas propriedades corres-
pondem exatamente quelas vistas na Seo 2.5.1 e sero revistas aqui para
facilitar a reteno.
2. Propriedades que alguns operadores possuem. Essas propriedades ainda no
foram estudadas e, portanto, requerem maior ateno do leitor.
3.6.1 Propriedades que Todos os Operadores Possuem
Qualquer operador de C possui as propriedades apresentadas a seguir.
Resultado
O resultado de um operador o valor resultante da aplicao do operador sobre seus
operandos. Por exemplo: a aplicao do operador + na expresso 2 + 3 resulta em 5.
Aridade
A aridade de um operador o nmero de operandos sobre os quais o operador atua.
De acordo com essa propriedade, os operadores de C so divididos em trs categorias:
Operadores unrios so operadores que requerem um operando
Operadores binrios so operadores que requerem dois operandos
Operador ternrio um operador que requer trs operandos
Por exemplo, o operador de soma, representado por +, tem aridade dois (i.e., ele
um operador binrio).
Precedncia
A precedncia de um operador determina sua ordem de aplicao com relao a outros
operadores. Isto , um operador de maior precedncia aplicado antes de um operador
de menor precedncia. Em C, operadores so agrupados em grupos de precedncia
que satisfazem as seguintes propriedades:
Todos os operadores que fazem parte de um mesmo grupo de precedncia
possuem a mesma precedncia.
Operadores que pertencem a diferentes grupos de precedncia possuem pre-
cedncias diferentes.
Essa propriedade foi discutida na Seo 2.5.1. Refra-se quela seo em caso de
dvidas.
Associatividade
Associatividade um conceito semelhante ao de precedncia no sentido de que am-
bos so utilizados para decidir a ordem de aplicao de operadores numa expresso.
Entretanto, diferentemente do que ocorre com precedncia, a associatividade utilizada
com operadores de mesma precedncia. Existem dois tipos de associatividade em C:
Associatividade esquerda: o operador da esquerda aplicado antes do ope-
rador da direita.
Associatividade direita: o operador da direita aplicado antes do operador
da esquerda.
Essa propriedade tambm foi discutida em maior profundidade na Seo 2.5.1.
Portanto, refra-se a ela em caso de dvidas.
120 | Captulo 3 Introduo Linguagem C
3.6.2 Propriedades que Alguns Operadores Possuem
Alm das propriedades j apresentadas, alguns operadores da linguagem C possuem as
propriedades adicionais apresentadas a seguir.
Efeito Colateral
Essa propriedade anloga ao efeito colateral (muitas vezes indesejvel) provocado por
um medicamento. Nessa analogia, o efeito principal do medicamento corresponde ao
resultado produzido pelo operador e o efeito colateral a alterao de valor produzida
pelo operador em um de seus operandos. Entretanto, no caso de operadores com efeito
colateral, muitas vezes, o efeito colateral produzido pelo operador o nico proveito
desejado. Em resumo, o efeito colateral de um operador consiste em alterar o valor de
um de seus operandos e, portanto, o operando sujeito a esse efeito colateral deve ser
uma varivel. Um exemplo de operador com efeito colateral o operador de atribui-
o (v. Seo 3.9).
Ordem de Avaliao
A ordem de avaliao de um operador indica qual dos operandos sobre os quais ele atua
avaliado primeiro. Portanto, essa propriedade s faz sentido para operadores com aridade
maior do que um (i.e., operadores binrios e ternrios). Apenas quatro operadores de
C possuem essa propriedade e esse fato frequentemente acarreta em expresses capazes
de produzir dois resultados vlidos possveis (v. exemplos nas Sees 3.9 e 3.11). Os
operadores de conjuno && e disjuno lgicas ||, que sero apresentados na Seo
3.7.3, so dois operadores que possuem ordem de avaliao defnida.
Curto Circuito
Essa propriedade faz com que, s vezes, apenas um dos operandos de um operador
binrio seja avaliado. Apenas os operadores lgicos binrios de conjuno e disjuno
possuem essa propriedade (v. Seo 3.7.3).
3.6.3 Uso de Parnteses
Conforme foi enfatizado na Seo 2.5.6, o uso de parnteses infuencia as propriedades
de precedncia, associatividade e, por conseguinte, resultado. Nenhuma outra proprie-
dade de operadores sofre infuncia do uso de parnteses.
3.7 Operadores e Expresses
Uma expresso uma combinao legal de operadores e operandos. Aquilo que cons-
titui uma combinao legal de operadores e operandos precisamente defnido para
cada operador da linguagem C.
3.7.1 Aritmticos
Uma expresso aritmtica uma combinao de operadores aritmticos e operandos
numricos que, quando avaliada, resulta num valor numrico. Os operandos de uma
expresso aritmtica podem incluir variveis, constantes ou chamadas de funes, que
resultem em valores numricos. Os operadores aritmticos bsicos de C so apresen-
tados na Tabela 33.
Operadores e Expresses | 121
OPERADOR OPERAO
-
Menos unrio (inverso de sinal)
+
Adio
-
Subtrao
*
Multiplicao
/
Diviso
%
Resto da diviso inteira
TABELA 33: OPERADORES ARITMTICOS DE C
A maioria dos operadores da Tabela 33 funciona como em aritmtica conven-
cional e em outras linguagens de programao, mas, em C, existem algumas diferenas.
Usando um compilador que segue um padro anterior a C99, quando um ou
ambos os operandos envolvidos numa diviso inteira so negativos, existem dois pos-
sveis resultados e o mesmo ocorre com resto de diviso inteira. Em compiladores que
seguem os padres mais recentes da linguagem C (C99 e C11), a diviso inteira tem
sempre um resultado nico possvel, que obtido como se o quociente da diviso re-
al dos respectivos operandos tivesse sua parte fracionria descartada. Por exemplo, o
quociente da diviso real de -17 por 5 -3.4; desprezando-se a parte fracionria desse
resultado, obtm-se -3, que o quociente da diviso inteira -17/5.
Tendo calculado o resultado de uma diviso inteira, o resto dessa mesma diviso
pode ser obtido por meio da frmula:
resto = numerador - quociente*denominador
Por exemplo, utilizando essa frmula e o resultado obtido para -17/5, tem-se que:
-17%5 igual a -17 -3*5, que igual a -17 + 15, que igual a -2
Operadores aritmticos so agrupados em grupos de precedncia conforme mostra
a Tabela 34. Operadores de um mesmo grupo nesta tabela tm a mesma precedncia.
Dentre os operadores apresentados nessa tabela, apenas o operador unrio associativo
direita; os demais so associativos esquerda. Por exemplo, a expresso:
- -2
seria interpretada como -(-2), visto que o operador - (unrio) associativo direita.
Note que, na expresso acima, h um espao em branco entre os dois traos. Isso evita
que o compilador interprete-os como operador de decremento (v. Seo 3.11).
GRUPO DE OPERADORES PRECEDNCIA
(unrio) Mais alta
*, /, %
+, (binrios) Mais baixa
TABELA 34: PRECEDNCIAS DE OPERADORES ARITMTICOS DE C
importante salientar que diviso inteira ou resto de diviso inteira por zero
uma operao ilegal que causa o trmino abrupto (aborto) da execuo de um pro-
grama que tenta realizar tal operao. Por outro lado, diviso real por zero no causa
aborto de programa, mas no produz um nmero real como resultado. Portanto, antes
122 | Captulo 3 Introduo Linguagem C
de efetuar qualquer operao de diviso ou resto de diviso, deve-se verifcar, por meio
de uma instruo if (v. Seo 4.6.1), se o divisor da operao zero.
3.7.2 Relacionais
Operadores relacionais so operadores binrios utilizados em expresses de compa-
rao. Os operandos de um operador relacional podem ser de qualquer tipo aritmti-
co. Os operadores relacionais de C so apresentados, com seus possveis resultados, na
Tabela 35, enquanto que a Tabela 36 exibe seus grupos de precedncia.
Note que os quatro primeiros operadores na Tabela 35 tm a mesma precedn-
cia, que menor do que as precedncias dos operadores aritmticos vistos antes. Os
dois ltimos operadores esto uma classe de precedncia abaixo dos quatro primeiros
operadores.
Observe que C e a linguagem algortmica apresentada no Captulo 2 possuem
operadores relacionais equivalentes. Entretanto, uma diferena fundamental que a
linguagem algortmica possui o tipo de dados booleano e expresses de comparao
resultam em verdadeiro ou falso. Em C, os resultados de uma expresso relacional
correspondem a um inteiro (0 ou 1). Observe ainda que os operadores relacionais cor-
respondentes nessas linguagens usam smbolos diferentes.
OPERADOR DENOMINAO APLICAO RESULTADO
> maior do que a > b 1 se a maior do b; 0, caso contrrio
>= maior ou igual a >= b
1 se a maior do que ou igual a b; 0,
caso contrrio
< menor do que a < b 1 se a menor do b; 0, caso contrrio
<= menor ou igual a <= b
1 se a menor do que ou igual a b; 0,
caso contrrio
== igualdade a == b 1 se a igual a b; 0, caso contrrio
!= diferente a != b 1 se a diferente de b; 0, caso contrrio
TABELA 35: OPERADORES RELACIONAIS
GRUPO DE OPERADORES PRECEDNCIA
>, >=, <, <=
Mais alta
==, !=
Mais baixa
TABELA 36: PRECEDNCIAS DOS OPERADORES RELACIONAIS DE C
O programador deve tomar cuidado para no usar inadvertidamente o smbolo =,
que representa o operador de igualdade em linguagem algortmica, em substituio ao
smbolo ==, que representa esse operador em C. Esse tipo de erro, muito comum em
programao em C, muitas vezes difcil de ser localizado, pois o uso por engano do
smbolo = ao invs de == , na maioria das vezes, sintaticamente legal, embora, frequen-
temente, resulte numa interpretao diferente da pretendida. Um exemplo concreto
dessa situao ser apresentado na Seo 4.6.1.
Conforme foi visto na Seo 3.4.3, nmeros reais podem ser representados aproxi-
madamente no computador. Por isso, operadores relacionais no devem ser usados para
Operadores e Expresses | 123
comparar nmeros reais da mesma maneira que eles so usados para comparar nmeros
inteiros. Na Seo 5.14.6, ser mostrado como nmeros reais podem ser comparados.
3.7.3 Lgicos
Operadores lgicos em C correspondem aos operadores de negao, conjuno e
disjuno da linguagem algortmica (v. Seo 2.5.4). Entretanto, diferentemente do
que ocorre na linguagem algortmica, os operadores lgicos em C podem receber como
operandos quaisquer valores numricos. Os operadores lgicos de C so apresentados
em ordem decrescente de precedncia na Tabela 37.
OPERADOR SMBOLO PRECEDNCIA
Negao
!
Mais alta
Conjuno
&&

Disjuno
||
Mais baixa
TABELA 37: OPERADORES LGICOS DE C EM ORDEM DECRESCENTE DE PRECEDNCIA
A aplicao de um operador lgico sempre resulta em 0 ou 1, dependendo dos
valores dos seus operandos. Os valores resultantes da aplicao desses operadores de
acordo com os valores de seus operandos so resumidos nas Tabelas 38 e 39.
X !X
0 1
diferente de 0
0
TABELA 38: RESULTADOS DO OPERADOR DE NEGAO (!)
X Y X && Y X || Y
0 0 0 0
0
diferente de 0
0 1
diferente de 0
0 0 1
diferente de 0 diferente de 0
1 1
TABELA 39: RESULTADOS DOS OPERADORES DE CONJUNO (&&) E DISJUNO (||)
Para memorizar a Tabela 39, voc precisa apenas considerar que a aplicao de
&& resulta em 1 apenas quando os dois operandos so diferentes de zero; caso contr-
rio, o resultado 0. De modo semelhante, X || Y resulta em 0 apenas quando ambos
os operandos so iguais a 0.
O operador lgico ! tem a mesma precedncia do operador aritmtico unrio, re-
presentado por , visto na Seo 3.7.1. Os operadores lgicos && e || tm precedn-
cias mais baixas do que operadores aritmticos e relacionais, mas no fazem parte de
um mesmo grupo de precedncia: o operador && tem precedncia mais alta do que
o operador ||. A Tabela 310 apresenta as precedncias relativas entre todos os opera-
dores vistos at aqui.
Os operadores && e || tm ordem de avaliao de operandos especifcada como
sendo da esquerda para a direita. Isto , o primeiro operando sempre avaliado em
primeiro lugar.
124 | Captulo 3 Introduo Linguagem C
GRUPO DE OPERADORES PRECEDNCIA
!, (unrios) Mais alta
*, /, %
+, - (binrios)
>, >=, <, <=
==, !=
&&

||
Mais baixa
TABELA 310: PRECEDNCIAS DE OPERADORES ARITMTICOS, RELACIONAIS E LGICOS DE C
A propsito, uma informao importante que merece ser memorizada a seguinte:
Todos os operadores unrios de C fazem parte de um mesmo grupo de precedn-
cia. Os operadores desse grupo possuem a segunda maior precedncia dentre
todos os operadores da linguagem C e a associatividade deles direita.
Apenas os operadores de acesso, que sero apresentados no Captulo 9, possuem
maior precedncia do que os operadores unrios.
Curto Circuito do Operador &&
Quando o primeiro operando do operador && zero, o segundo operando no
avaliado e o resultado da operao zero. Por exemplo, quando o valor de a for zero
na expresso:
(a != 0) && (b/a > 4)
o operando a != 0 resulta em 0 e o operando b/a > 4 no avaliado pois considera-
-se que, para que toda a expresso resulte em 0, basta que um dos operandos seja 0.
Curto Circuito do Operador ||
Quando o primeiro operando do operador || diferente de zero, o segundo operando no
avaliado e o resultado da operao 1. Por exemplo, se o valor de x for 5 na expresso:
(x > 0) || (y < 0)
o operando x > 0 resulta em 1 e o operando y < 0 no avaliado.
3.8 Defnies de Variveis
Em programao, uma defnio de varivel tem trs objetivos: (1) prover uma in-
terpretao para o espao em memria ocupado pela varivel, (2) fazer com que seja
alocado espao sufciente para conter a varivel e (3) associar esse espao a um identi-
fcador (i.e., o nome da varivel).
Em C, toda varivel precisa ser defnida antes de ser usada. Uma defnio de va-
rivel em C consiste de um identifcador representando o tipo da varivel seguido do
nome da varivel. Variveis de um mesmo tipo podem ainda ser defnidas juntas e se-
paradas por vrgulas. Por exemplo, a defnio:
int minhaVar, i, j;
responsvel pela alocao em memria das variveis minhaVar, i e j como sendo
do tipo int.
Operador de Atribuio | 125
recomendvel que identifcadores que representem categorias diferentes de
componentes de um programa sigam notaes diferentes de composio para facilitar
a identifcao visual de cada componente. No caso de variveis, as recomendaes so
as seguintes:
Inicie o nome de uma varivel com letra minscula.
Se o nome da varivel for composto, utilize letra maiscula no incio de cada
palavra seguinte, inclusive palavras de ligao (p. ex., preposies e conjunes)
No utilize subtrao.
Seguem mais algumas recomendaes para a escolha de identifcadores para variveis:
Escolha nomes que sejam signifcativos (p. ex., matricula mais signifca-
tivo do que x ou m).
Evite utilizar nomes de variveis que sejam muito parecidos ou que difram
em apenas um caractere (p. ex., primeiraNota e segundaNota so melhores
do que nota1 e nota2).
Evite utilizar l (ele) e o () como nomes de variveis pois so facilmente con-
fundidos com 1 (um) e 0 (zero). Esse problema tambm pode ser evitado com
uma escolha adequada de fonte para edio de programas, como aquela usada
nesse livro. (A propsito, o nome dessa fonte Adobe Source Code Pro e pode
ser obtida gratuitamente via internet.)
Outra recomendao que melhora a legibilidade de programas o uso de espaos
horizontais para alinhar identifcadores numa seo de declarao. Por exemplo:
int umaVariavel;
static int outraVariavel;
3.9 Operador de Atribuio
Uma das instrues mais simples em C a instruo de atribuio. Uma instruo
desse tipo preenche o espao em memria representado por uma varivel com um valor
determinado e sua sintaxe tem a seguinte forma geral:
varivel = expresso;
A interpretao para uma instruo de atribuio a seguinte: a expresso (lado
direito) avaliada e o valor resultante armazenado no espao de memria represen-
tado pela varivel (lado esquerdo).
Quando um espao em memria alocado para conter uma varivel, o contedo
desse espao (i.e., o valor da prpria varivel) pode ser indeterminado (v. Seo 5.12.3).
Isso signifca que no se deve fazer nenhuma suposio sobre o valor de uma varivel
antes que a mesma assuma um valor explicitamente atribudo. s vezes, desejvel que
uma varivel assuma certo valor no instante de sua defnio. Essa iniciao pode ser
feita em C combinando-se a defnio da varivel com a atribuio do valor desejado.
Por exemplo, suponha que se deseje atribuir o valor inicial 0 a uma varivel inteira
denominada minhaVar. Ento, isso poderia ser feito por meio da seguinte iniciao:
int minhaVar = 0;
Uma instruo de atribuio uma expresso e o sinal de igualdade utilizado em
atribuio representa o operador principal dessa expresso. Esse operador faz parte de
um grupo de operadores que tm uma das mais baixas precedncias dentre todos os
126 | Captulo 3 Introduo Linguagem C
operadores de C. De fato, apenas o operador vrgula (v. Seo 4.9) possui precedncia
menor do que esse grupo de operadores.
O operador de atribuio possui efeito colateral, que consiste exatamente na alte-
rao de valor causada na varivel (operando) que ocupa o lado esquerdo da expresso.
Esse operador possui associatividade direita e o resultado da aplicao desse operador
o valor recebido pela varivel no lado esquerdo da expresso de atribuio. Em virtude
das suas propriedades, o operador de atribuio pode ser utilizado para a execuo de
mltiplas atribuies numa nica linha de instruo. Por exemplo, se x, y e z so do
tipo int, a atribuio composta:
x = y = z = 1;
resulta na atribuio de 1 a z, z a y e y a x, nessa ordem. Nesse caso, x, y e z tero, no
fnal da execuo da instruo, o mesmo valor, mas isso nem sempre acontece numa
atribuio mltipla, pois podem ocorrer converses implcitas, como mostra o seguin-
te exemplo:
int i;
double d;
i = d = 2.5;
Nesse exemplo, f recebe o valor 2.5, mas i recebe o valor 2 (o valor de d con-
vertido em int).
Exerccio: Que valores receberiam i e d na atribuio d = i = 2.5?
Com ocorre com a maioria dos operadores de C, o operador de atribuio no possui
ordem de avaliao de operandos defnida. Isso, aliado ao fato de o operador de atri-
buio possuir efeito colateral, pode dar origem a expresses capazes de produzir dois
resultados diferentes, mas aceitveis. Por exemplo, no trecho de programa:
int x = 0, y = 0;
(x = 1)*(x + 2);
a ltima expresso pode produzir dois resultados diferentes, dependendo de qual dos
operandos [(x = 1) ou (x + 2)] avaliado primeiro. Isto , se o primeiro operando
for avaliado antes do segundo, o resultado ser 3 (1 vezes 3); enquanto que, se o segun-
do operando for avaliado antes do primeiro, o resultado ser 2 (1 vezes 2). Qualquer
dos dois resultados vlido porque a padro da linguagem C no especifca qual dos
dois operandos deve ser avaliado primeiro. Portanto, a expresso (x = 1)*(x + 2)
no portvel em C.
Examinando detalhadamente a expresso do ltimo exemplo, podem-se descobrir
quais so os ingredientes de uma expresso capaz de produzir dois resultados distintos
e legtimos:
Uso de operador sem ordem de avaliao de operandos especifcada. No
ltimo exemplo, o operador de multiplicao (*) no tem ordem de avaliao
de operandos defnida, mas se esse operador for substitudo, por exemplo, pe-
lo operador &&, a expresso resultante (x = 1) && (x + 2) ser portvel.
Uso de um operador com efeito colateral. No exemplo em questo, o
operador de atribuio possui efeito colateral; se esse operador for substitu-
do, por exemplo, pelo operador representtado por >, a expresso resultante
(x > 1)*(x + 2) ser portvel.
Converses de Tipos | 127
Uma varivel que sofre efeito colateral faz parte dos dois operandos de um
operador sem ordem de avaliao de operandos defnida. No exemplo em
questo, a varivel x aparece nos dois operandos do operador *. Se uma das
ocorrncias dessa varivel for substituda por outra varivel, a expresso resul-
tante torna-se portvel. Por exemplo, (x = 1)*(y + 2) portvel.
3.10 Converses de Tipos
3.10.1 Converses Implcitas
C permite que operandos de tipos aritmticos diferentes sejam misturados em expresses.
Entretanto, para que tais expresses faam sentido, o compilador executa converses
implcitas (ou automticas). Essas converses muitas vezes no incluem arredonda-
mento e so responsveis por resultados inesperados. Portanto, o programador deve
estar absolutamente ciente das transformaes feitas implicitamente pelo compilador
antes de misturar tipos numa expresso; caso contrrio, melhor evitar defnitivamen-
te essa mistura.
Existem quatro situaes nas quais converses so feitas implicitamente pelo com-
pilador de C. Duas delas sero discutidas a seguir, enquanto as demais sero discutidas
no Captulo 5.
Diz-se que dois tipos so compatveis entre si quando eles so iguais ou quando
qualquer valor de um tipo pode ser convertido implicitamente num valor do outro
tipo. Assim, todos os tipos aritmticos discutidos neste livro so compatveis entre si.
Entretanto, isso no signifca que no ocorre perda de informao durante tal conver-
so (v. adiante).
Converso de Atribuio
Nesse tipo de converso, o valor do lado direito de uma atribuio convertido no tipo
da varivel do lado esquerdo. Um problema que pode ocorrer com esse tipo de conver-
so surge quando o tipo do lado esquerdo mais curto do que o tipo do lado direito da
atribuio. Por exemplo, se c uma varivel do tipo char, a atribuio:
c = 936;
pode resultar, na realidade, na atribuio do valor 168 a c. Por que isso ocorre? Primeiro,
o valor 936 grande demais para caber numa varivel do tipo char (que, relembran-
do, ocupa apenas um byte). Segundo, pode-se observar que 936 representado em 16
bits pela sequncia:
00000011 10101000
Mas, como valores do tipo char devem ser contido em apenas 8 bits, o compilador
pode considerar apenas os 8 bits de menor ordem:
10101000
que correspondem a 168 em base decimal.
Converses entre nmeros reais e inteiros tambm podem ser problemticas.
Claramente, a atribuio de um nmero real a uma varivel inteira pode causar perda
de informao, pois nmeros reais so usualmente capazes de conter nmeros com
ordens de grandeza bem maiores do que o maior valor permitido para uma varivel
inteira. Por exemplo, se i uma varivel do tipo int, a seguinte atribuio:
128 | Captulo 3 Introduo Linguagem C
i = 1.85E100;
faz com que a i seja atribudo o valor 2147483647 numa dada implementao de C.
O estranho valor atribudo varivel i surgiu em virtude da ocorrncia de overfow (v.
Seo 4.12.7); i.e., uma varivel do tipo int no capaz de armazenar um valor to
grande quanto aquele que lhe foi atribudo.
Os erros decorrentes de overfow nos exemplos apresentados acima so fceis de
entender. Mas, numa atribuio de um valor real a uma varivel inteira podem ocor-
rer erros decorrentes de truncamento que so bem mais difceis de detectar e corrigir.
Truncar um nmero signifca desprezar alguns de seus algarismos e, quando um
nmero real convertido em nmero inteiro, sua parte fracionria truncada. Em vir-
tude da relativa complexidade envolvida com erros de truncamento, a esse tpico ser
dedicada uma seo especial (Seo 6.5 do Captulo 6).
Apesar de os tipos reais serem usualmente capazes de armazenar valores maiores
do que os tipos inteiros em termos de ordem de grandeza, a atribuio de um nme-
ro inteiro a uma varivel de um tipo real pode causar perda de preciso, pois o tipo
real poder no ser capaz de representar todos os algarismos signifcativos do nmero
inteiro, que, nesse caso, ser arredondado. Entretanto, problemas dessa natureza so
improvveis com os tipos double e int usados neste livro.
Converso Aritmtica Usual
Quando um operador possui operandos de tipos diferentes, um deles convertido no
tipo do outro, de modo que eles passem a ter o mesmo tipo. Essa categoria de conver-
so denominada converso aritmtica usual, porque ela afeta operandos aritmti-
cos, mas ela se aplica a operadores de qualquer natureza e obedece as seguintes regras:
Quando um operando um valor inteiro (i.e., do tipo int ou char) e outro
operando do mesmo operador do tipo double, o operando inteiro conver-
tido em double antes de a expresso ser avaliada. Precisamente, isso signifca
que o valor inteiro usado pelo programador ser substitudo por um valor do
tipo double quando o programa for compilado.
Quando um operando do tipo int e o outro operando do mesmo operador
char, o operando do tipo char convertido em int antes de a expresso ser ava-
liada. Essa categoria de converso denominada converso de alargamento e
no traz nenhum dano para um programa. por causa dela que programadores
conscientes usam o tipo int em declaraes de variveis e parmetros mesmo
que eles armazenem apenas valores que caberiam numa varivel do tipo char.
3.10.2 Converso Explcita
O programador pode especifcar converses explicitamente em C antepondo ao valor
que deseja transformar o nome do tipo desejado entre parnteses. Por exemplo, supo-
nha que se tenham as seguintes linhas de programa em C:
int i1 = 3, i2 = 2;
double d;
d = i1/i2;
Nesse caso, em virtude de converses implcitas, d receber o valor 1.0, o que tal-
vez no seja o esperado. Entretanto, se um dos inteiros for promovido explicitamente
a double o resultado ser 1.5, o que pode ser obtido do seguinte modo:
Incremento e Decremento | 129
d = (double) i1/i2;
A construo (tipo), como (double), trata-se de mais um operador em C, deno-
minado operador de converso explcita. Esse operador tem a mesma precedncia e
associatividade dos outros operadores unrios. Portanto, a expresso anterior inter-
pretada como:
((double) i1)/i2
Observe que, se a expresso i1/i2 for colocada entre parnteses, a converso se-
r feita, de forma redundante, sobre o resultado da expresso e o resultado ser nova-
mente 1.0.
O uso do operador de converso explcita, mesmo quando ele desnecessrio,
capaz de melhorar a legibilidade de programas. Por exemplo, suponha que d do tipo
double e i do tipo int. Ento, na atribuio:
i = (int) d;
o operador (int) utilizado apenas para indicar que o programador est ciente de que
ocorre uma converso para int. Funcionalmente, esse operador redundante, uma vez
que essa transformao ocorreria implicitamente se o operador no fosse includo. No
entanto, o uso do operador torna clara essa converso.
3.11 Incremento e Decremento
Os operadores de incremento e decremento so operadores unrios que, quando apli-
cados a uma varivel, adicionam-lhe ou subtraem-lhe 1, respectivamente. Esses opera-
dores aplicam-se a variveis numricas ou ponteiros (v. Seo 5.2). Os operadores de
incremento e decremento so representados respectivamente pelos smbolos ++ e -- e
tm a mesma precedncia e associatividade de todos os operadores unrios.
Existem duas verses para cada um desses operadores: (1) prefxa e (2) sufxa.
Sintaticamente, essa classifcao refere-se posio do operador em relao ao seu
operando. Se o operador aparece antes do operando (p. ex., ++x), ele um operador
prefxo; caso contrrio (p. ex., x++), ele sufxo. Todos esses operadores produzem efei-
tos colaterais nas variveis sobre as quais atuam. Esses efeitos colaterais correspondem
exatamente ao incremento (i.e., acrscimo de 1 ao valor) ou decremento (i.e., subtrao
de 1 do valor) da varivel.
Com relao a efeitos colaterais, no existe diferena quanto ao uso da forma pre-
fxa ou sufxa de cada um desses operadores. Isto , qualquer verso do operador de
incremento produz o mesmo efeito de incremento e qualquer verso do operador de
decremento produz o mesmo efeito de decremento.
A diferena entre as verses prefxa e sufxa de cada um desses operadores est no
resultado da operao. Os operadores sufxos produzem como resultado o prprio valor
da varivel sobre a qual atuam; por outro lado, operadores prefxos resultam no valor da
varivel aps o efeito colateral (i.e., incremento ou decremento) ter ocorrido. Portanto,
se o resultado de uma operao de incremento ou de decremento no for utilizado,
no faz nenhuma diferena se o operador utilizado prefxo ou sufxo. Por exemplo,
no trecho de programa a seguir:
int y, x = 2;
y = 5*x++;
y recebe o valor 10, enquanto que se a instruo contendo incremento fosse escrita como:
130 | Captulo 3 Introduo Linguagem C
y = 5*++x;
y receberia o valor 15. Em ambos os casos, entretanto, a varivel x seria incrementada
para 3 (i.e., o efeito colateral seria o mesmo).
Supondo que x uma varivel numrica ou um ponteiro, os resultados e efeitos
colaterais dos operadores de incremento e decremento so resumidos na Tabela 311.
OPERAO DENOMINAO VALOR DA EXPRESSO EFEITO COLATERAL
x++
incremento sufxo o mesmo de x adiciona 1 a x
++x
incremento prefxo o valor de x mais 1 adiciona 1 a x
x--
decremento sufxo o mesmo de x subtrai 1 de x
--x
decremento prefxo o valor de x menos 1 subtrai 1 de x
TABELA 311: OPERADORES DE INCREMENTO E DECREMENTO
Muitas vezes, o programador est interessado apenas no efeito colateral do operador
de incremento ou decremento. Nesse caso, a escolha da verso de operador utilizada
absolutamente irrelevante. Ou seja, o programador deve preocupar-se com a diferena
entre as verses desses operadores apenas quando os valores resultantes de expresses
formadas por esses operadores forem utilizados.
Do mesmo modo como ocorre com o operador de atribuio (v. Seo 3.9), no
recomendvel o uso de uma varivel afetada por um operador de incremento ou decre-
mento na mesma expresso em que ocorre tal incremento ou decremento. Por exemplo,
considere o seguinte trecho de programa:
int i, j = 4;
i = j * j++;
Conforme j foi visto, a linguagem C no especifca qual dos operandos da mul-
tiplicao avaliado primeiro e, portanto o resultado a ser atribudo a i ir depender
da livre interpretao do compilador. Nesse caso, h dois resultados possveis: 16 ou
20 (verifque isso).
O programador tambm deve evitar (ou, pelo menos, tomar bastante cuidado
com) o uso de operadores com efeitos colaterais, como os operadores de incremento e
decremento, com os operadores lgicos && e ||. O problema agora que, conforme
visto na Seo 3.7.3, o compilador nem sempre avalia completamente algumas expres-
ses lgicas. Como exemplo, considere a expresso:
(a > b) && (c == d++)
Nessa situao, a varivel d seria incrementada apenas quando a fosse maior do
que b e, talvez, o programador desejasse que ela fosse incrementada sempre que essa
expresso fosse avaliada.
3.12 Comentrios
Comentrios em C so quaisquer sequncias de caracteres colocadas entre os delimi-
tadores de comentrios /* e */. Caracteres entre delimitadores de comentrios so
totalmente ignorados por um compilador de C e, portanto, no existe nenhuma res-
trio em relao a esses caracteres. Por exemplo:
/* Isto um comentrio acentuado em bom Portugus */
Comentrios | 131
De acordo com o padro ISO no permitido o uso aninhado de comentrios
desse tipo; i.e., um comentrio no interior de outro comentrio. Entretanto, algumas
implementaes de C aceitam isso, o que pode ser bastante til na depurao de pro-
gramas, pois permite excluir, por meio de comentrios, trechos de programa que j
contenham comentrios (v. Seo 6.4.3).
O padro C99 introduz o delimitador de comentrio //. Caracteres que seguem esse
delimitador at o fnal da linha que o contm so ignorados pelo compilador. Exemplo:
// Outro comentrio acentuado em bom Portugus
Esse tipo de comentrio pode ser aninhado em comentrios do tipo anterior:
/*
x = 10; // Isto um comentrio
*/
E vice-versa:
x = 10; // Isto /* outro */ comentrio
O objetivo principal de comentrios explicar o programa para outros programa-
dores e para voc mesmo quando for l-lo algum tempo aps sua escrita. Um programa
sem comentrios fora o leitor a fazer inferncias para tentar entender o que e como
o programa faz. Aqui, sero apresentados alguns conselhos sobre quando, como e onde
comentar um programa a fm de clarifc-lo.
O melhor momento para comentar um trecho de um programa ou algoritmo
exatamente quando esse trecho est sendo escrito. Isso se aplica especialmente queles
trechos de programa contendo sutilezas, inspiraes momentneas ou coisas do gnero,
que o prprio programador ter difculdade em entender algum tempo depois. Alguns
comentrios passveis de ser esquecidos (p. ex., a data de incio da escrita do programa)
tambm devem ser acrescentados no momento da escrita do programa. Outros co-
mentrios podem ser acrescentados quando o programa estiver pronto, embora o ideal
continue sendo comentar todo o programa medida que ele escrito. Se voc deixar
para comentar um programa algum tempo aps t-lo concludo, pode ser que no seja
capaz de descrever tudo que fez. Ou seja, o que provavelmente era bvio quando vo-
c escreveu o programa pode ter se tornado indecifrvel quando estiver escrevendo os
comentrios algum tempo depois.
Comentrios devem ser claros e dirigidos para programadores com alguma expe-
rincia na linguagem de programao utilizada. Isto , comentrios devem incluir tudo
aquilo que um programador precisa saber sobre um programa e nada mais. Eles no
tm que ser didticos como alguns comentrios apresentados aqui e em outros textos
de ensino de programao. Esses comentrios didticos so teis nesses textos que tm
exatamente o objetivo de ensinar, mas comentrios num programa real tm o objetivo
de explicar o programa para programadores e no o de ensinar a um leigo na lingua-
gem o que est sendo feito. Por exemplo, o comentrio na seguinte linha de instruo
x = 2; /* O contedo de x passa a ser 2 */
aceitvel num texto que se prope a ensinar programao, mas no faz sentido num
programa real.
A melhor forma de adquirir prtica na escrita de comentrios lendo programas
escritos por programadores profssionais e observando os vrios estilos de comentrios
utilizados.
132 | Captulo 3 Introduo Linguagem C
Existem dois formatos bsicos de comentrios: comentrio de bloco e coment-
rio de linha, que devem ser utilizados conforme sugerido aqui ou de acordo com a
necessidade. Em qualquer caso, voc no precisa seguir os formatos dos modelos suge-
ridos. Isto , voc livre para usar sua criatividade para criar seu prprio estilo de co-
mentrio; o que se espera que o contedo corresponda quele sugerido nos formatos
de comentrios apresentados a seguir.
Blocos de comentrio so utilizados no incio do programa [i.e., no incio do
arquivo contendo a funo main()] com o objetivo informativo de apresentar o pro-
psito geral do programa, data de incio do projeto, nome do programador, verso do
programa, nota de direitos autorais (copyright) e qualquer outra informao pertinen-
te. Por exemplo:
/****
*
* Ttulo do Programa: MeuPrograma
*
* Autor: Jos da Silva
*
* Data de Incio do Projeto: 10/11/2012
* ltima modificao: 19/11/2012
*
* Verso: 2.01b
*
* Descrio: Este programa faz isto e aquilo.
*
* Dados de Entrada: Este programa espera os seguintes dados...
*
* Dados de Sada: Este programa produz como sada o seguinte...
*
* Uso: Este programa deve ser usado assim...
*
* Copyright 2012 Jos da Silva Software Ltda.
*
****/
Outros itens comumente usados em comentrios iniciais de programas incluem:
Propsito do programa (i.e., para que o programa foi construdo?).
Se o programa contm cdigo desenvolvido por outrem (d crdito a quem
o merece).
Como devem ser os formatos dos arquivos que seu programa l ou escreve.
Restries que se aplicam ao programa (p. ex., Este programa no checa erros
de entrada de dados).
Histrico de revises: o que e quando o programa foi modifcado e por quem.
Tratamento de erro: quando o programa detecta um erro, o que ele faz?
Observaes: inclua qualquer comentrio relevante sobre o programa que ain-
da no tenha sido apresentado.
Comentrios de bloco dessa natureza fazem parte dos exemplos de programao
obtidos via download no site do livro (www.ulysseso.com/ip).
Bibliotecas | 133
3.13 Bibliotecas
Em programao, biblioteca uma coleo de componentes que o programador pode
incluir em seus programas. Em C, tais componentes incluem, por exemplo, constantes
simblicas (v. Seo 3.15), tipos de dados derivados (v. Seo 9.2) e funes. Funo
o nome que se d a um subprograma na linguagem C e assunto a ser discutido em
profundidade no Captulo 5. O uso de componentes prontos para ser incorporados
em programas facilita sobremaneira o trabalho dos programadores.
3.13.1 A Biblioteca Padro de C
A biblioteca padro de C aquela preconizada pelo padro ISO dessa linguagem.
Isso signifca que todo compilador de C que adere ao padro ISO deve ser distribudo
acompanhado dessa biblioteca. A biblioteca que acompanha um compilador pode in-
cluir componentes adicionais alm daqueles recomendados pelo padro de C. O uso
de componentes especfcos de uma determinada biblioteca num programa prejudica
sua portabilidade.
A biblioteca padro de C dividida em grupos de componentes que tm alguma
afnidade entre si. Por exemplo, existem componentes para entrada e sada, processa-
mento de strings, operaes matemticas, etc. Cada grupo de componentes, denomi-
nado mdulo, possui dois arquivos associados:
Um arquivo-objeto que contm as implementaes dos componentes do m-
dulo previamente compiladas.
Um arquivo de texto, denominado cabealho, que contm defnies parciais
(aluses) legveis das funes implementadas no arquivo-objeto correspon-
dente. Um arquivo de cabealho pode ainda conter, entre outros componen-
tes, defnies de tipos (v. Seo 9.2) e constantes simblicas (v. Seo 3.15).
Arquivos de cabealho normalmente tm a extenso .h (que derivada de
header; i.e., cabealho em Ingls).
Para utilizar algum componente de um mdulo de biblioteca num programa,
deve-se incluir o arquivo de cabealho desse mdulo usando uma diretiva #include
(usualmente, no incio do programa) com o formato:
#include <nome-do-arquivo>
ou:
#include "nome-do-arquivo"
Normalmente, o primeiro formato de incluso usado para cabealhos da biblioteca
padro, enquanto que o segundo formato usado para cabealhos de outras bibliotecas.
Linhas de um programa em C que comeam com o smbolo # so denominadas
diretivas. Elas so processadas por um programa, denominado pr-processador, cuja
execuo antecede o processo de compilao propriamente dito. Diretivas possuem
sintaxe prpria. Por exemplo, diretivas no terminam com ponto e vrgula, como ins-
trues da linguagem C.
Como foi afrmado, um arquivo de cabealho contm informaes incompletas
sobre funes. Mas, apesar de incompletas, essas informaes so sufcientes para o
compilador checar se uma determinada chamada de funo correta. As defnies
134 | Captulo 3 Introduo Linguagem C
completas das funes aludidas num cabealho esto contidas no arquivo-objeto as-
sociado ao cabealho. Para que um programa-fonte que usa uma funo de biblioteca
possa ser transformado em programa executvel, necessrio que o arquivo-objeto re-
sultante de sua compilao seja ligado ao arquivo-objeto que contm o cdigo compi-
lado da funo. Essa ligao feita por um linker (v. Seo 3.16.2).
Atualmente, 29 cabealhos fazem parte da biblioteca padro de C. A Tabela 312
apresenta os cabealhos mais comumente utilizados e seus propsitos.
CABEALHO PROPSITO
<stdio.h>
Entrada e sada em geral, incluindo leitura de dados via teclado (v.
Captulo 10), escrita de dados na tela (v. Seo 3.14.1) e proces-
samento de arquivos (v. Captulos 10 e 11).
<stdlib.h>
Funes srand() e rand() usadas em gerao de nmeros alea-
trios (v. Seo 4.11).
Alocao dinmica de memria (Captulo 12)
<time.h>
Funo time() usada com srand() em gerao de nmeros aleat-
rios (v. Seo 4.11).
<string.h> Processamento de strings (v. Captulo 8).
<ctype.h> Classifcao e transformao de caracteres (v. Captulo 8).
<math.h> Operaes matemticas com nmeros reais [p. ex., sqrt(), pow()].
TABELA 312: PRINCIPAIS CABEALHOS DA BIBLIOTECA PADRO DE C
Apenas alguns dos vrios componentes da biblioteca padro de C sero apresen-
tados neste livro devido sua natureza introdutria.
3.13.2 A Biblioteca LEITURAFACIL
A biblioteca LeituraFacil foi desenvolvida com o objetivo de facilitar o aprendizado de
programao removendo parte da complexidade inerente linguagem C com respeito
a leitura de dados via teclado. O processo de instalao dessa biblioteca foi descrito no
Captulo 1. Na Seo 3.14.2, ser mostrado como utilizar alguns de seus componentes.
3.13.3 Outras Bibliotecas
Um compilador pode vir acompanhado de outras bibliotecas alm da biblioteca pa-
dro de C. Essas bibliotecas facilitam ainda mais a criao de programas, mas tm co-
mo grande desvantagem o fato de no serem portveis. A falta de portabilidade afige
particularmente bibliotecas dedicadas construo de interfaces grfcas aderentes a
uma plataforma. Por exemplo, uma biblioteca especfca para construo de interfaces
grfcas para sistemas da famlia Windows no tem nenhuma utilidade para construo
de interfaces grfcas (p. ex., KDE, Gnome) para o sistema Linux.
3.14 Entrada via Teclado e Sada via Tela
As funes responsveis pelas operaes de entrada e sada em C fazem parte de um m-
dulo da biblioteca padro de C denominado stdio
[1]
. Para utilizar essas funes deve-se
incluir o cabealho stdio.h, que contm informaes sobre elas, por meio da diretiva:
[1] Esse nome vem de standard input/output; i.e., entrada/sada padro.
Entrada via Teclado e Sada via Tela | 135
#include <stdio.h>
Quando encontra uma diretiva #include, o pr-processador de C a substitui pe-
lo contedo do arquivo que se deseja incluir. Por exemplo, quando a diretiva acima
processada, o contedo do arquivo stdio.h inserido no local do programa onde ela
se encontra. Assim, quando encontrar uma chamada de uma funo referenciada no
arquivo stdio.h, o compilador ser capaz de verifcar se a chamada correta. Se voc
no incluir o respectivo arquivo de cabealho para uma funo de biblioteca que deseja
utilizar em seu programa, qualquer chamada dela ser tratada pelo compilador como,
por exemplo, identifcador no declarado, visto que nem elas fazem parte da linguagem
C em si nem voc as declarou explicitamente
[2]
.
3.14.1 Escrita de Dados na Tela
A funo printf() equivalente em C instruo escreva da linguagem algortmica
apresentada no Captulo 2. Isto , ela permite a escrita de constantes, variveis ou ex-
presses de quaisquer tipos na tela do computador. A funo printf() tambm permite
a escrita de strings. No entanto, diferentemente da instruo escreva da linguagem
algortmica, a funo printf() requer que seja especifcado o formato de cada item que
ela escreve. Essa especifcao feita por meio de um string (tipicamente constante),
denominado string de formatao, de modo que uma chamada da funo printf()
assume o seguinte formato:
printf(string-de-formatao, e
1
, e
2
, ..., e
n
);
onde cada e
i
pode ser uma constante, varivel, expresso ou um string. Para cada item
e
i
a ser escrito na tela, deve haver um especifcador de formato no interior do string
de formatao que indica como esse item deve ser escrito.
A Tabela 313 enumera os especifcadores de formato mais comuns utilizados
pela funo printf().
ESPECIFICADOR DE FORMATO O VALOR SER APRESENTADO COMO...
%c Caractere
%s Cadeia de caracteres (string)
%d ou %i Inteiro em base decimal
%f Nmero real em notao convencional
%e (%E) ou %g (%G) Nmero real em notao cientfca
TABELA 313: ESPECIFICADORES DE FORMATO COMUNS UTILIZADOS POR printf()
Alm de especifcadores de formato, o string de formatao pode ainda conter
outros caracteres. Quando um caractere do string de formatao no faz parte de um
especifcador de formato, ele escrito exatamente como ele . Por exemplo, ao fnal da
execuo do trecho de programa a seguir:
int n = 3;
printf("O quadrado de %d e' %d.", n, n*n);
ser escrito o seguinte na tela:
[2] Chamar uma funo signifca fazer com que ela seja executada, como ser visto no Captulo 5. Cada item
entre parnteses numa chamada de funo denominado parmetro. Parmetros so separados por vrgulas.
136 | Captulo 3 Introduo Linguagem C
O quadrado de 3 e' 9.
Observe que na chamada de printf() do ltimo exemplo, o string de formatao
contm dois especifcadores de formato do mesmo tipo: %d. Eles indicam que h dois
parmetros alm do string de formatao que devem ser escritos em formato de inteiro
na base decimal. Esses parmetros so a varivel n e a expresso n*n.
Especifcadores de formato podem ser ainda mais especfcos ao indicar como os
parmetros fnais de printf() devem ser escritos. Por exemplo, pode-se indicar que um
nmero real deve ser exibido com um mnimo de cinco casas, sendo duas delas deci-
mais, por meio do especifcador %5.2f. O seguinte programa e o respectivo resultado
apresentado na tela demonstram os efeitos de alguns especifcadores de formato.
#include <stdio.h>
int main(void)
{
int i1 = 40, i2 = 123;
double x1 = 123.45, x2 = 123.456789;
printf("\n\t>>> Especificador %%d: |%d|", i1);
printf("\n\t>>> Especificador %%5d: |%5d|", i1);
printf("\n\t>>> Especificador %%-5d: |%-5d|", i1);
printf("\n\t>>> Especificador %%5.3d: |%5.3d|\n", i1);
printf("\n\t>>> Especificador %%10.3f: |%10.3f|", x1);
printf("\n\t>>> Especificador %%10.3e: |%10.3e|", x1);
printf("\n\t>>> Especificador %%-10g: |%-10g|\n", x1);
printf("\n\t>>> Formato padrao int (%%d): %d\n", i2);
printf( "\t>>> Com especificador de precisao (%%2.8d): "
"%2.8d\n", i2 );
printf("\n\t>>> Formato padrao double (%%f): %f\n", x2);
printf( "\t>>> Com especificador de precisao (%%-10.2f):"
" %-10.2f\n", x2 );
return 0;
}
Esse programa apresenta o seguinte resultado:
>>> Especificador %d: |40|
>>> Especificador %5d: | 40|
>>> Especificador %-5d: |40 |
>>> Especificador %5.3d: | 040|
>>> Especificador %10.3f: | 123.450|
>>> Especificador %10.3e: |1.235e+002|
>>> Especificador %-10g: |123.45 |
>>> Formato padrao int (%d): 123
>>> Com especificador de precisao (%2.8d): 00000123
>>> Formato padrao double (%f): 123.456789
>>> Com especificador de precisao (%-10.2f): 123.46
Um estudo mais aprofundado de formatao de sada est alm do escopo deste
livro, mas vrios exemplos no decorrer do texto mostram formas alternativas de uso dos
especifcadores apresentados na Tabela 313 (v. exemplo apresentado na Seo 3.19.4).
Entretanto, o aprendiz no deve dar muita importncia a especifcadores de formato.
verdade que seus programas podero apresentar sadas de dados mais elegantes se
Entrada via Teclado e Sada via Tela | 137
voc conhec-los bem. Mas, por outro lado, voc no ser considerado um bom pro-
gramador apenas por conhecer uma grande quantidade de especifcadores de formato.
Outra funo de sada da biblioteca padro de C, que menos frequentemente
usada do que printf(), a funo putchar(). Essa funo recebe como entrada um va-
lor do tipo int e escreve na tela o caractere correspondente a esse valor. Por exemplo,
a instruo:
putchar('A');
resultaria na escrita de A na tela.
3.14.2 Leitura de Dados via Teclado
Leitura de dados introduzidos via teclado um dos aspectos mais difceis de progra-
mao. Escrever um programa robusto capaz de responder a quaisquer caracteres di-
gitados pelo usurio uma tarefa que poucos programadores so capazes de realizar.
Em particular, dominar completamente as funes de entrada de dados via teclado da
biblioteca padro de C uma misso complicada para alunos de introduo progra-
mao (v. Seo 10.9).
Para facilitar o aprendizado, este livro usa a biblioteca LeituraFacil desenvolvida com
o objetivo de lidar com as complexidades inerentes s funes de entrada via teclado
da biblioteca padro de C, que sero apresentadas no Captulo 10.
Para utilizar as funes da biblioteca LeituraFacil, voc dever t-la instalado
de acordo com as recomendaes da Seo 1.6.4. Se voc utilizar CodeBlocks, dever
tambm ter confgurado esse IDE conforme preconizado na Seo 1.7.2. necessrio
ainda incluir o arquivo de cabealho dessa biblioteca em cada programa que usa qual-
quer de suas funes por meio da diretiva:
#include "leitura.h"
As funes da biblioteca LeituraFacil so apresentadas na Tabela 314.
FUNO O QUE FAZ EXEMPLO
LeCaractere() L um caractere
int c;
c = LeCaractere();
LeInteiro() L um nmero inteiro
int i;
i = LeInteiro();
LeReal() L um nmero real
double d;
d = LeReal();
LeString() L um string (v. Seo 8.5.1)
char ar[5];
LeString(ar, 5);
LeOpcao()
L um caractere que satisfaz certo
critrio (v. Seo 5.11.2)
int c;
c = LeOpcao("ABCabc");
TABELA 314: FUNES DA BIBLIOTECA LEITURAFACIL
As trs primeiras funes apresentadas na Tabela 314 so muito fceis de usar,
conforme mostram os exemplos. As demais funes sero discutidas medida que seus
usos se fzerem necessrios.
Alm de serem fceis de usar, as funes da biblioteca LeituraFacil so capazes
de tornar um programa robusto do ponto de vista de entrada de dados. Por exemplo,
se um programa contm o seguinte fragmento:
#include <stdio.h>
138 | Captulo 3 Introduo Linguagem C
#include "leitura.h"
...
int numero;
printf("Digite um numero inteiro: ");
numero = LeInteiro();
e, quando esse trecho de programa for executado, o usurio digitar, digamos, abc, o
programa informar o usurio sobre o erro cometido e solicitar a introduo de um
novo valor, como mostrado a seguir:
Digite um numero inteiro: abc
>>> O valor digitado e' invalido. Tente novamente
>
Obter os mesmos resultados apresentados pelas funes da biblioteca LeituraFacil
usando as funes de leitura via teclado da biblioteca padro de C no to trivial,
conforme ser visto no Captulo 10.
3.14.3 Uso de Prompts
Se o programador deseja obter algum tipo de informao de um usurio de seu progra-
ma, o primeiro passo descrever precisamente para o usurio que tipo de informao o
programa espera obter dele. Assim, toda entrada de dados deve ser precedida por uma
informao dirigida ao usurio sobre aquilo que o programa espera que ele introduza.
Essa solicitao de dados apresentada ao usurio denominada prompt e deve preceder
qualquer instruo de entrada de dados via teclado. Normalmente, utiliza-se a funo
printf() para essa fnalidade.
Para apresentar o prompt mais adequado ao usurio do programa, o programador
deve, com a devida antecedncia, conhecer o perfl de usurio de seu programa para
ser capaz de comunicar-se na lngua dele. Quer dizer, se o programa destina-se a usu-
rios de certa rea de conhecimento especfca, no h problema em usar jarges dessa
rea, mas, se os usurios podem apresentar nveis diversos de conhecimento, jarges
devem ser evitados.
Um engano frequente entre programadores iniciantes assumir que os usurios
de seus programas so versados em computao. Assim, um uso de jargo, que mui-
tas vezes imperceptvel para o programador, diz respeito queles jarges usados em
sua prpria rea de conhecimento. Tendo isso em mente, ele usa em prompts jarges
tpicos de profssionais dessa rea, como, por exemplo: digite um string. Hoje em dia,
digitar j se tornou uma expresso comum, mas, provavelmente, um usurio comum
no faz a menor ideia do signifcado de string. Portanto, revise seus prompts e substitua
ou elimine qualquer jargo exclusivo de sua rea.
3.15 Constantes Simblicas
A linguagem C permite que se associe um identifcador a um valor constante. Esse
identifcador denominado constante simblica e pode ser defnido em C por meio
de uma diretiva #defne. Por exemplo, suponha que se deseje denominar PI o valor
3.14, ento a seguinte diretiva seria utilizada:
#define PI 3.14
Quando o programa contendo essa defnio compilado, o compilador substitui
todas as ocorrncias de PI por seu valor (i.e., 3.14).
Como Construir um Programa II: Implementao | 139
O uso de constantes simblicas em um programa tem dois objetivos principais:
1. Tornar o programa mais legvel. Por exemplo, PI mais legvel do que o
valor 3.14.
2. Tornar o programa mais fcil de ser modifcado. Por exemplo, suponha que
o valor constante 3.14 aparece em vrios pontos de seu programa. Se voc
desejasse modifcar esse valor (digamos para 3.14159) voc teria de encontrar
todos os valores antigos e substitu-los. Entretanto se esse valor fosse repre-
sentado por uma constante simblica defnida no incio do programa, voc
precisaria fazer apenas uma modifcao na prpria defnio da constante.
O uso prtico de constantes simblicas ser discutido em maiores detalhes na
Seo 4.10.5.
A linguagem algortmica apresentada no Captulo 2 pode ser expandida para per-
mitir o uso de constantes simblicas. Nesse caso, para declarar uma constante simb-
lica, precede-se seu nome com constante e termina-se a declarao com o smbolo =
seguido do valor que a constante representa, como mostra o seguinte exemplo:
constante PI = 3.14
3.16 Como Construir um Programa II: Implementao
A construo de um programa um processo cclico no sentido de que se pode retornar
a uma etapa anterior quando a etapa corrente no apresenta um resultado satisfatrio.
A Figura 31 ilustra grafcamente o processo cclico de construo de um programa
de pequeno porte. Programas mais complexos do que aqueles discutidos neste texto
requerem projetos bem mais sofsticados que constituem assunto de disciplinas da rea
de Engenharia de Software.
A Seo 2.9 descreveu em detalhes como deve ser o projeto de soluo de um
problema simples por meio de um programa. Em resumo, as etapas envolvidas num
projeto dessa natureza so:
1. Anlise do problema (v. Seo 2.9.1)
2. Refnamento do algoritmo (v. Seo 2.9.2)
3. Teste do algoritmo (v. Seo 2.9.3)
Nas sees a seguir, sero exploradas as etapas implicadas na implementao da
soluo do problema, que so:
4. Codifcao do algoritmo (v. Seo 3.16.1)
5. Construo do programa executvel (v. Seo 3.16.2)
6. Teste do programa (v. Seo 3.16.3)
Normalmente, a etapa de construo de um programa executvel to simples
para programadores com alguma experincia (v. Seo 3.16.2) que no considerada
separada da etapa de codifcao. Por isso, a Etapa 5 no aparece na Figura 31.
140 | Captulo 3 Introduo Linguagem C
Anlise do Problema
Algoritmo
Teste do Algoritmo
Teste do Programa
Codifcao do Algoritmo
(Programa)
Projeto de Soluo Implementao da Soluo
FIGURA 31: PROCESSO DE CRIAO DE UM PROGRAMA
3.16.1 Etapa 4: Codifcao do Algoritmo
Aps completa a etapa fnal de projeto, a etapa seguinte consiste em codifcar o algoritmo
de modo a obter um programa-fonte. Essa ltima etapa resumida no seguinte quadro:
4. Escreva o programa-fonte usando um editor de programas.
4.1 Traduza cada instruo do algoritmo numa instruo equivalente se-
guindo as convenes da linguagem de programao escolhida.
4.2 Edite a traduo resultante do passo anterior. A execuo desse passo
resulta num programa-fonte.
Se a linguagem algortmica utilizada na fase de projeto for prxima linguagem
de programao escolhida para codifcao, a Etapa 4.1 no deve oferecer nenhuma
difculdade. Alm disso, as Etapas 4.1 e 4.2 podem ser executadas como uma unidade.
Isto , com um pouco de experincia, pode-se traduzir um algoritmo e editar o progra-
ma traduzido num nico passo, sem que se tenha que fazer uma traduo manuscrita.
A Seo 3.17 mostra como realizar a Etapa 4 na prtica.
3.16.2 Etapa 5: Construo do Programa Executvel
O quadro a seguir resume o que deve ser realizado na Etapa 5:
5. Utilize um compilador e linker compatveis com a linguagem de programa-
o e o sistema operacional utilizados e construa um programa executvel.
Conforme foi visto no Captulo 1, o processo de compilao resulta num arquivo-
-objeto, mas esse arquivo no necessariamente um programa executvel. O arquivo-
-objeto resultante da compilao precisa ser ligado a outros arquivos-objeto que por-
ventura contenham funes ou variveis utilizadas pelo programa. Essa tarefa realizada
por meio de um linker, conforme foi mencionado na Seo 1.2.2. A Figura 32 ilustra,
Como Construir um Programa II: Implementao | 141
de modo simplifcado, o processo de transformao de um programa constitudo de
um nico arquivo-fonte em programa executvel.
Cdigo-Objeto
Programa-fonte
Programa executvel
Bibliotecas
(cdigo-objeto)
Compilador
Linker
FIGURA 32: PROCESSO DE CONSTRUO DE UM PROGRAMA EXECUTVEL
A efetivao dessa etapa pode resumir-se a nico clique de mouse ou pode levar
algum tempo em virtude de necessrias correes de erros de compilao ou ligao. A
Seo 3.17 apresenta algumas opes disponveis para concretizao dessa etapa e a Seo
3.18 ensina como lidar com erros de compilao e ligao que so comuns nessa fase.
3.16.3 Etapa 6: Teste do Programa
O fato de no ter ocorrido erro de compilao ou ligao na Etapa 5 no signifca que
o programa executvel obtido naquela etapa esteja correto. preciso test-lo com ca-
sos de entrada qualitativamente diferentes (v. Seo 2.9.3). Portanto, na Etapa 6, o
programa deve ser executado para verifcar se ele funciona conforme o esperado (i.e.,
conforme foi especifcado na defnio do problema). Assim, deve-se examinar o pro-
grama sob vrias circunstncias (casos de entrada) e verifcar se, em cada uma delas, o
programa funciona adequadamente.
Normalmente, qualquer programa no trivial possui erros de programao. Portanto,
o objetivo maior quando se testa um programa encontrar erros que impeam o seu
funcionamento normal.
Tcnicas utilizadas para testes de programas complexos constituem uma disciplina
parte e uma apresentao completa dessas tcnicas est alm do escopo deste livro.
Portanto, aqui, apenas duas das tcnicas mais comuns e fceis de ser implementadas
sero descritas.
A primeira tcnica conhecida como inspeo de programa e consiste em ler
atenciosamente o programa e responder uma lista de verifcao contendo questes
referentes a erros comuns em programao na linguagem de codifcao do programa,
como o Apndice C disponvel no site do livro (www.ulysseso.com/ip).
A segunda tcnica comum de verifcao de programas conhecida como teste
exaustivo e consiste em utilizar dados tpicos de entrada e simular manualmente a exe-
cuo do programa, do mesmo modo que simulada a execuo de um algoritmo (v.
Seo 2.9.3). Num teste exaustivo, importante que sejam utilizados casos de entrada
142 | Captulo 3 Introduo Linguagem C
qualitativamente diferentes. Tambm, igualmente importante que sejam testadas no
apenas entradas vlidas, mas tambm algumas entradas invlidas.
Se o programa apresenta um comportamento considerado anormal, ele deve ser
depurado. Isto , as instrues responsveis pelos erros devem ser encontradas e corri-
gidas. A Seo 6.4 apresenta algumas tcnicas elementares de depurao.
3.16.4 Saltando Etapas
bastante tentador, mesmo para programadores mais experientes, apressar-se em ini-
ciar a escrita de um programa no computador to logo se tenha uma ideia daquilo que
seria a soluo para o problema em questo. Mas, do mesmo modo, tambm comum
gastar-se muito mais tempo removendo erros de um programa do que escrevendo-o.
Parece humanamente impossvel construir-se um programa no trivial que no
contenha erros (bugs), mas um programa escrito s pressas muito mais susceptvel a
erros do que um programa que implementa a soluo de um problema bem estudado
previamente conforme foi preconizado na Seo 2.9. Portanto, o conselho a ser seguido :
Resista tentao de escrever o programa no computador to logo voc tenha
uma vaga ideia de como deve ser a soluo do problema.
Enquanto no adquire experincia sufciente para saltar etapas, siga os procedi-
mentos prescritos na Seo 2.9 e no presente captulo. Programadores experientes so
capazes de escrever programas-fonte de relativa simplicidade diretamente num editor de
programas e, com muito treinamento, voc tambm ser capaz de realizar isso. Mas, en-
quanto no atingir a plenitude de conhecimento em programao, resista a essa tentao.
Se voc ainda no consegue saltar etapas do processo de desenvolvimento de um
programa, no se sinta frustrado: siga todas as etapas prescritas, pois, com a prtica ad-
quirida, voc conseguir escrever cada vez mais um nmero maior de programas sem
ter que escrever previamente seus algoritmos em pseudolinguagem. Nunca esquea,
entretanto, que no se devem escrever programas mais complexos sem planej-los pre-
viamente (Etapas 13 da Seo 2.9). O tempo gasto no planejamento de um pro-
grama recuperado em sua depurao. Ou seja, frequentemente, a depurao de um
programa mal planejado leva muito mais tempo do que a escrita do programa em si.
3.17 Programas Monoarquivos em C
Existem dois tipos de sistemas de execuo de programas escritos em C:
1. Sistemas com hospedeiro. Programas executados em sistemas com hospedeiro
so, tipicamente, sujeitos superviso e ao suporte de um sistema operacional.
Esses programas devem conter uma funo main(), que a primeira funo
chamada quando comea a execuo do programa. Todas as construes de C
discutidas neste livro so voltadas para programas dessa natureza.
2. Sistemas livres. Programas executados em sistemas livres no possuem hospe-
deiro ou sistema de arquivos e uma implementao de C para tais sistemas no
precisa atender a todas as recomendaes impostas para sistemas com hospe-
deiro. Num programa desse tipo, o nome e o tipo da primeira funo chamada
quando o programa executado so determinados pela implementao. Este
livro no lida com esse tipo de programa.
Programas Monoarquivos em C | 143
Este livro dedica-se a ensinar como construir programas simples executados em
linha comando (console) de um sistema operacional. Esses programas so denominados
monoarquivos, pois eles consistem de um nico arquivo-fonte. A seguir, mostrar-se-
como editar um programa-fonte e construir um programa executvel em C.
3.17.1 Estrutura de um Programa Simples em C
Um programa simples em C, consistindo de um nico arquivo-fonte e que usa a bi-
blioteca LeituraFacil, possui o seguinte formato geral:
#include <stdio.h> /* Para usar printf() */
/* Inclua aqui outros cabealhos padro utilizados no programa */
#include "leitura.h" /* Para usar LeituraFacil */
/* Inclua aqui definies de constantes */
/* simblicas utilizadas no programa */
int main(void)
{
/* Inclua aqui definies de variveis */
/* que sero necessrias no seu programa */
/* Inclua aqui instrues que executem as aes */
/* necessrias para funcionamento do seu programa. */
/* I. e., traduza em C cada passo de seu algoritmo. */
return 0; /* Informa o sistema operacional que */
/* o programa terminou normalmente */
}
A instruo:
return 0;
que aparece ao fnal da maioria dos programas escritos em C indica que o programa foi
executado sem anormalidades. Em geral, o valor usado com return no interior de main()
indica para o sistema operacional ou outro programa que cause a execuo do programa
em questo se a execuo desse programa foi bem sucedida ou no. Assim, quando o
programador prev algum problema que impea a execuo normal do programa, ele
usa um valor diferente de zero. Por exemplo, quando o programa CodeBlocks invoca
o compilador GCC para compilar um programa, ele capaz de saber se a compilao
foi bem sucedida ou no checando o valor retornado pelo GCC.
O uso de zero para representar sucesso na execuo de um programa pode pa-
recer um contrassenso. Afnal, quando uma ao bem sucedida no se costuma lhe
atribuir zero. Porm, suponha, por exemplo, que um programa para ser bem sucedido
precisa processar um arquivo que deve ter um formato especfco. Ento, pelo menos,
dois fatos podem impedir que o programa seja bem sucedido: (1) o arquivo no en-
contrado e (2) o arquivo no tem o formato esperado. Quando um desses fatos ocorre,
se o programa desejar indicar por que no foi bem sucedido, ele pode usar um valor
diferente para cada categoria de erro. Portanto, se zero indicasse que o programa no
foi bem sucedido, ele no poderia discriminar os dois erros. Por isso, convencionou-
-se que zero indicaria sucesso e valores diferentes de zero indicariam a ocorrncia de
alguma anormalidade.
144 | Captulo 3 Introduo Linguagem C
3.17.2 Como Criar um Programa-fonte
Se voc estiver usando um editor de texto comum (o que no recomendvel) ou um
editor de programas, crie um programa-fonte do mesmo modo como voc procede na
criao de um arquivo de texto qualquer. Se voc estiver usando CodeBlocks, siga o
procedimento descrito na Seo 1.7.3.
3.17.3 Tabulao: Inimiga da Programao com Estilo
Se voc usar as recomendaes de endentao apresentadas neste livro, provavelmente,
seus programas sero legveis e esteticamente agradveis de ler. Infelizmente, editores
de texto e de programas incorporam um vilo que pode destruir a esttica de um pro-
grama. Esse vilo a tabulao.
Se voc usar tabulao (i.e., a tecla [TAB] na parte superior esquerda do teclado),
sofrer uma grande decepo quando seu programa-fonte for aberto num outro editor
de texto e voc verifcar que parte do seu trabalho em prol do bom estilo de progra-
mao foi por gua abaixo. E a decepo ser ainda maior se voc misturar tabulaes
com espaos em branco obtidos com a barra de espaos. Por exemplo, no trecho de
programa a seguir, a defnio de varivel int x e a instruo x = 10 foram endentadas
de maneiras diferentes: a referida defnio foi endentada usando quatro espaos (com
a barra do teclado), enquanto que a instruo foi endentada por meio da tecla [TAB]
confgurada com quatro espaos. Apesar de estas duas linhas aparecem perfeitamente
alinhadas no editor de programas no qual o programa-fonte foi editado, aqui (e em
outros editores de texto) elas aparecem desalinhadas.
int main(void)
{
int x; /* Endentado com quatro espaos */
x = 10; /* Tabulao de quatro espaos */
return 0;
}
Bons editores de texto podem ser confgurados para usar espaos em branco em vez
de tabulaes, mas, mesmo assim, so necessrios alguns cuidados extras. Para evitar o
uso de tabulaes no editor do CodeBlocks, siga o seguinte procedimento:
1. Clique na opo Editor... do menu Settings.
2. Localize a seo denominada TAB options.
3. Desmarque a opo Use TAB charactere.
4. Marque a opo TAB indents.
5. Digite 3 na caixa precedida por TAB size in spaces.
A Figura 3-3 mostra o resultado fnal do ltimo procedimento.
FIGURA 33: CONFIGURANDO OPES DE TABULAO EM CODEBLOCKS
Programas Monoarquivos em C | 145
FIGURA 34: CONFIGURANDO OPES DE ENDENTAO EM CODEBLOCKS
Para certifcar-se que tabulao realmente no usada na edio de programas,
confgure as opes de endentao seguindo os seguintes passos:
1. Clique na opo Editor... do menu Settings.
2. Localize a seo denominada Indent options.
3. Marque a opo Auto indent. Usando essa opo, quando ocorre uma quebra
de linha, a linha seguinte ser alinhada com a linha precedente, a no ser que
a opo Smart indent (a seguir) esteja selecionada.
4. Marque a opo Smart indent. Fazendo uso dessa opo o editor reconhece
que algumas instrues precisam ser endentadas em relao a outras e efetua
endentao levando isso em considerao. Por exemplo, se voc no usa essa
opo e quebra a linha aps o abre-chaves da funo main(), a prxima linha
ser alinhada com o abre-chaves. Usando essa opo, a prxima linha ser en-
dentada em relao ao abre-chaves.
5. Se desejar, marque a opo Brace Completion. Empregando essa opo, todos
os smbolos que tm abertura e fechamento aparecem automaticamente aos
pares. Por exemplo, quando voc digita abre-parnteses, o fecha-parnteses
aparece automaticamente e o mesmo ocorre com chaves, apstrofos, aspas,
etc. Essa opo pode ser incmoda para quem est acostumado com editores
que no a possuem. De qualquer modo, selecione essa opo e experimente-a;
se no a apreciar desmarque-a novamente.
6. Se desejar, marque a opo Backspace unindents. Usando essa opo, quando
voc pressiona a tecla [BACKSPACE] antes do primeiro caractere de uma linha
que no espao em branco, so apagados tantos espaos quanto forem os es-
paos de endentao. Se essa opo no estiver selecionada, apenas um espao
excludo. Normalmente, essa opo til.
7. Se voc enfrenta problemas com a visualizao da estrutura de um programa,
marque a opo Show indentation guides. Experimente-a e veja como seu pro-
grama aparece na janela de edio. Se gostar, permanea com ela; caso con-
trrio, desmarque-a.
8. Na caixa de seleo identifcada por Show spaces, selecione (temporariamente)
a opo Always. Com essa opo, o editor apresenta espaos em branco como
pontos e as abominveis tabulaes como setas (). Use essa opo tempo-
rariamente at certifcar-se que o editor no est lhe traindo e detonando a
formatao de seu programa.
Ao fnal da execuo desse ltimo procedimento, a seo de confgurao do editor
intitulada Indent options dever apresentar-se como mostrado na Figura 3-4.
146 | Captulo 3 Introduo Linguagem C
3.17.4 Usando um Molde de Programa em CodeBlocks
Em breve, voc ir notar que a maioria dos programas apresentados neste livro com-
partilham muitos trechos iguais ou semelhantes. Por exemplo:
Todo programa precisa incluir um cabealho de apresentao, como aquele
visto como exemplo na Seo 3.12.
Todo programa hospedado escrito em C possui uma funo main() que, na
maioria das vezes, comea e termina do mesmo modo.
Todo programa escreve algo na tela. Portanto, sempre necessrio incluir o
arquivo stdio.h que possibilita usar a funo printf().
A maioria dos programas leem dados via teclado. Portanto, na maioria das
vezes, necessrio incluir o arquivo leitura.h.
Tambm, uma boa ideia incluir um exemplo de execuo do programa co-
locado entre comentrios aps o fnal do programa.
No seria bom comear um programa com todos esses itens comuns j includos,
em vez de comear com um arquivo vazio? O editor do IDE CodeBlocks permite que
se especifque o contedo de cada arquivo criado. Por exemplo, suponha que voc de-
seja que cada arquivo novo contenha o seguinte:
/****
*
* Ttulo:
*
* Autor:
*
* Data de Criao: //2014
* ltima modificao: //2014
*
* Descrio:
*
* Entrada:
*
* Sada:
*
****/
#include <stdio.h> /* printf() */
#include "leitura.h" /* LeituraFacil */
int main(void)
{
return 0;
}
/******************* Exemplo de Execuo *******************
***********************************************************/
Para obter o resultado desejado, siga o seguinte procedimento:
1. No menu Settings, escolha a opo Editor...
2. No painel da esquerda da janela que surge em seguida, clique sobre o cone
denominado Default code.
3. Certifque-se que, na caixa de seleo intitulada Type of fle no topo da janela,
est selecionada a opo C/C++ Source File.
Programas Monoarquivos em C | 147
4. No painel da direita da referida janela digite o contedo com o qual voc de-
seja iniciar cada arquivo criado pelo editor do CodeBlocks, como mostra a
Figura 3-5.
FIGURA 35: DEFAULT CODE EM CODEBLOCKS
5. Para concluir a operao, clique sobre o boto OK.
Existe um atalho mais rpido e prtico para a tarefa descrita acima, que con-
siste em copiar o contedo do arquivo Molde.c, que se encontra no site do livro
(www.ulysseso.com/ip) e col-lo no espao mencionado. O contedo desse arquivo
o mesmo que aparece nesta seo.
Para experimentar o efeito do procedimento descrito, crie um arquivo-fonte con-
forme foi visto na Seo 1.7.3 e observe o resultado.
3.17.5 Criando um Programa Executvel
Na Seo 1.7.4, mostrou-se como obter um programa executvel a partir de um pro-
grama-fonte usando o IDE CodeBlocks. Essa a opo mais rpida e fcil de se obter
o resultado desejado.
Uma opo mais trabalhosa e que requer alguma intimidade com o sistema ope-
racional utilizado por meio da invocao do compilador e do linker via linha de
148 | Captulo 3 Introduo Linguagem C
comando. Nesse caso, em uma janela de terminal aberta no diretrio onde se encontra
o programa-fonte, deve-se emitir o seguinte comando:
gcc Wall std=c99 pedantic arquivo-fonte lleitura o arquivo-executvel
Emitindo esse comando, voc invocar o compilador e o linker simultaneamen-
te com as opes recomendadas para compilar e ligar o programa-fonte denominado
arquivo-fonte e o resultado ser um arquivo executvel denominado arquivo-exe-
cutvel. Se, eventualmente, voc digitar o comando esquematizado acima de modo
incorreto e conhecer razoavelmente a interface utilizada pelo sistema operacional, saber
corrigir os erros sem ter que digitar todo o comando novamente. Caso contrrio, voc
desperdiar muito tempo com essa opo de compilao e mais recomendvel que
voc use o programa denominado compile que se encontra no site dedicado a este livro.
3.18 Lidando com Erros de Sintaxe e Advertncias
3.18.1 C ou C++?
Provavelmente, a primeira frustrao com que se depara um iniciante em programao
em C decorrente do uso de compilador errado. Esse problema oriundo do fato de a
maioria dos compiladores de C tambm serem compiladores de C++ e essas linguagens,
apesar de compartilharem diversas semelhanas, so diferentes e seus padres seguem
caminhos independentes. De fato, esses compiladores incorporam dois tradutores:
um para C e outro para C++. Alm disso, como padro, esses compiladores assumem
que, a priori, arquivos-fonte que representam programas em C usam a extenso .c e
aqueles que representam programas em C++ possuem extenso .cpp. Portanto, para
evitar problemas, no use esta ltima extenso em seus programas-fonte. Por exem-
plo, usando GCC, o seguinte programa compilado normalmente se a extenso do
arquivo-fonte for .c:
#include <stdio.h>
int main(void)
{
const int x = 5;
int *p = &x;
*p = 10;
return 0;
}
Entretanto, o mesmo programa no compilado (em virtude de erro de sintaxe)
se a extenso do arquivo-fonte for .cpp.
Mesmo quando um programa consegue ser compilado por compiladores de C e
C++ providos por um mesmo fabricante, os resultados apresentados pelos programas
executveis obtidos podem ser diferentes. Por exemplo, quando o seguinte programa:
include <stdio.h>
int main(void)
{
printf("sizeof('A') = %d", sizeof('A'));
return 0;
}
Lidando com Erros de Sintaxe e Advertncias | 149
compilado com GCC e, em seguida, executado, ele apresenta como resultado:
sizeof('A') = 4
quando a extenso do arquivo-fonte .c. Mas, se a extenso desse arquivo for trocada
para .cpp, o resultado :
sizeof('A') = 1
Concluindo, siga sempre o seguinte conselho quando compilar um programa em C:
Certifque-se que est realmente usando um compilador de C quando
compilar seus programas escritos nessa linguagem. Alm disso, no
use a extenso .cpp para nomes de programas-fonte escritos em C.
3.18.2 Erros de Compilao
Sintaxe refere-se s regras de uma linguagem de programao que regem a construo
de programas escritos nessa linguagem. Um erro de compilao (tambm denominado
erro de sintaxe) ocorre em virtude de uma violao das regras de sintaxe da linguagem
ora em uso e um compilador capaz de traduzir um programa apenas quando ele est
livre de qualquer erro de sintaxe. Isto , um programa contendo erros de sintaxe no
pode ser nem compilado nem executado.
Quando um compilador tenta traduzir um programa e, durante o processo, des-
cobre algum erro de sintaxe, ele apresenta uma ou mais mensagens de diagnstico que
explicam a causa do erro (ou, pelo menos, tentam explicar...).
Qualquer programador, independentemente de sua experincia, comete erros de
sintaxe. Programadores inexperientes provavelmente comentem erros dessa natureza
por falta de familiaridade com a linguagem de programao utilizada. Por outro lado,
programadores mais experientes os comentem em virtude da rapidez com que produ-
zem cdigo ou por mera distrao. Nesse aspecto, uma diferena entre programadores
experientes e iniciantes que, para os primeiros, erros dessa natureza no causam pre-
ocupao e so corrigidos fcil e rapidamente. Para programadores iniciantes, corrigir
erros de compilao pode demandar muito tempo e constituir uma experincia marti-
rizante, principalmente por causa da falta de preciso com que compiladores apontam
os erros e linguagem enigmtica que muitas vezes usam.
Erros de sintaxe podem ser provocados por deslizes de digitao decorrentes do
pressionamento acidental de uma tecla em vez de outra. Exemplos de erros de digitao
corriqueiros decorrentes da proximidade de teclas so descritos abaixo:
Trocar ' por " ou vice-versa.
Trocar as teclas {, [, }, ] entre si.
Trocar as teclas ponto, vrgula e ponto e vrgula entre si.
Uso das teclas de acento agudo () ou grave (`) em substituio a apstrofos.
Nem acento agudo nem acento grave so usados em programao (a no ser
em comentrio, o que raro).
Outros erros de sintaxe frequentemente cometidos so enumerados a seguir:
Omisso de parnteses depois de main().
Omisso de abre-chaves ou fecha-chaves.
Digitao incorreta de uma palavra-chave (p. ex., doble em vez de double) ou
um nome de funo (p. ex., print em vez de printf). No caso de erro de digitao
150 | Captulo 3 Introduo Linguagem C
incorreta de palavra-chave, se voc estiver usando um editor de programas com
colorao de sintaxe, o erro pode ser percebido imediatamente, pois palavras-
-chaves so dispostas com uma formatao destacada (p. ex., em negrito).
No envolver strings constantes entre aspas. Novamente, se voc estiver usando
um editor com colorao de sintaxe, esse erro facilmente visualizado porque
strings constantes tm um colorido destacado.
Omisso de ponto e vrgula ao fnal de uma instruo ou declarao.
Incluso de ponto e vrgula ao fnal de diretivas (i.e., linhas do programa
que comeam com #). Iniciantes em programao muitas vezes adotam duas
abordagens extremas em relao ao uso de ponto e vrgula: ou esquecem com
frequncia de us-lo, ou o usam em locais em que no so necessrios ou so
indevidos.
Esquecer-se de incluir o cabealho referente a uma funo de biblioteca. Os
cabealhos mais comumente usados aqui so aqueles apresentados na Tabela
312 (v. Seo 3.13.1).
Usar variveis que no foram previamente declaradas.
Chamar uma funo com um nmero errado de parmetros ou com parme-
tros de tipos incompatveis com a defnio da funo (v. Seo 5.5).
Aplicao de incremento ou decremento sobre uma expresso. Por exemplo:
(x - 2)++ /* No compila*/
3.18.3 Mensagens de Erros
Mensagens de erro emitidas por um compilador indicam que seu programa est sinta-
ticamente incorreto e, portanto, no pode ser compilado (e muito menos executado).
Uma instruo ou declarao considerada ilegal quando no consegue ser compilada
devido a erro de sintaxe.
importante observar que um nico erro pode originar duas ou mais mensagens
de erro. Portanto, enquanto voc no adquire experincia sufciente para perceber is-
so, d ateno a cada mensagem de erro individualmente e na ordem em que elas so
apresentadas. Isto , tente resolver uma mensagem de erro de cada vez e re-compile o
programa depois de cada tentativa de correo.
Considere como exemplo o seguinte programa-fonte e suponha que o nome do
arquivo que o contm seja Erro1.c.
#include <stdio.h>
int main(void)
{
int i = 10;
printf( "i = %d\n", i)
return 0;
}
Esse programa contm um erro de sintaxe proposital e, como o programa di-
minuto, esse erro facilmente enxergado por qualquer programador com alguma ex-
perincia em C. Mas, um iniciante pode ter alguma difculdade para perceber que o
erro a falta ponto e vrgula ao fnal da instruo printf(). Se voc tentar compilar o
Lidando com Erros de Sintaxe e Advertncias | 151
programa acima usando GCC por meio de qualquer mtodo descrito na Seo 3.17.5,
receber como resposta a seguinte mensagem de erro:
C:\Programas\Erro1.c In function 'main':
C:\Programas\Erro1.c 9 error: expected ';' before 'return'
Se voc estiver usando CodeBlocks, essa mensagem ser apresentada no painel
inferior da janela com algum embelezamento para facilitar o entendimento, mas, em
essncia, o contedo das mensagens de erro obtidas com o compilador GCC executado
em linha de comando ou por intermdio de CodeBlocks o mesmo.
Mensagens de erro apresentadas pelo GCC comeam com o nome completo do
arquivo (i.e., incluindo seu caminho desde a raiz do sistema de arquivos at o diretrio
onde ele se encontra) seguido do nome da funo na qual a instruo que originou a
mensagem de erro se encontra. Por exemplo, a linha:
C:\Programas\Erro1.c In function 'main':
indica que ocorreu erro na funo main() do arquivo Erro1.c encontrado no diret-
rio (pasta) C:\Programas. As linhas seguintes descrevem os erros encontrados nessa
funo. Essas linhas comeam (novamente) com o nome completo do arquivo seguido
por error, dois pontos e o nmero da linha em que o erro foi detectado. No exemplo
em questo, h apenas um erro e uma linha correspondente a esse erro:
C:\Programas\Erro1.c 9 error: expected ';' before 'return'
O que essa mensagem de erro quer dizer que o compilador esperava encontrar
um ponto e vrgula antes da instruo return que se encontra na linha 9. Note que
o compilador talvez no tenha indicado o erro no local que voc esperava, que seria
a linha 7, que contm a instruo printf() que no foi devidamente terminada com
ponto e vrgula. Mas, embora parea estranho primeira vista, o compilador est abso-
lutamente correto na indicao do erro e a raciocnio empregado por ele o seguinte:
1. necessrio um ponto e vrgula para encerrar a instruo printf() antes do
incio da prxima instruo.
2. Como, nesse caso, o uso de espaos em branco no faz a menor diferena para
o compilador, o ponto e vrgula ausente pode ser colocado em qualquer lo-
cal entre printf() e return, e no necessariamente ao fnal da linha contendo
printf(). Ou seja, embora, do ponto de vista de estilo, seja recomendvel que
o ponto e vrgula seja colocado realmente nessa posio, para o compilador,
isso irrelevante.
3. O compilador encontra a instruo return sem antes ter encontrado o referi-
do ponto e vrgula. Assim, ele indica que houve erro na linha contendo essa
ltima instruo. Portanto, o compilador est absolutamente correto quando
informa que esperava um ponto e vrgula antes dessa instruo. Para compro-
var isso, coloque ponto e vrgula em qualquer local entre printf() e return e
voc ver que a mensagem de erro no mais aparecer.
Diante do que foi exposto, pode-se enunciar a seguinte afrmao em relao a
mensagens de erro emitidas por um compilador:
Raramente, uma mensagem de erro indica a linha onde o programador
esperava que o erro fosse indicado. Isto , o erro pode ter ocorrido algu-
mas linhas antes daquela qual a mensagem de erro faz referncia.
Mas, se serve de consolo, a seguinte afrmao tambm verdadeira:
152 | Captulo 3 Introduo Linguagem C
Um erro de sintaxe nunca ocorre numa linha posterior quela referida
numa mensagem de erro.
Apesar de o compilador muitas vezes apresentar mensagens de erro vagas e dif-
ceis de compreender, com a experincia adquirida aps encontrar vrias situaes se-
melhantes, em pouco tempo, voc ser capaz de facilmente encontrar e corrigir erros
apontados pelo compilador.
3.18.4 Mensagens de Advertncia
Mensagens de advertncia no impedem que um programa executvel seja criado. No
entanto, elas indicam situaes que podem causar o mau funcionamento do programa.
Portanto, nunca ignore completamente uma mensagem de advertncia. Em vez disso,
leia e entenda por que cada mensagem de advertncia foi gerada. Se, eventualmente,
voc decidir desprezar uma dada mensagem de advertncia, convena-se de que isso
no trar consequncias danosas ao seu programa. A observncia desse conselho pode
lhe resguardar de muita dor de cabea na depurao de seus programas.
Exemplos de Mensagens de Advertncia
A seguir, sero apresentados alguns exemplos de mensagens de advertncia com suges-
tes sobre como lidar com elas.
Exemplo 1
Considere o seguinte programa como exemplo e suponha que seu arquivo-fonte de-
nominado Advertencia1.c:
#include <stdio.h>
int main(void)
{
int i;
printf( "i = %d\n", i);
return 0;
}
Esse ltimo programa absolutamente correto do ponto de vista sinttico. Em
outras palavras, ele compilado sem problemas por qualquer compilador aderente a
algum padro ISO de C. Entretanto, um compilador decente que tenha sido invocado
com a opo de apresentao do maior nmero possvel de advertncias (p. ex., Wall
no GCC) apresentar uma mensagem de advertncia aps compilar esse programa. Por
exemplo, o compilador GCC emitir a seguinte mensagem:
C:\Programas\Advertencia1.c: In function 'main':
C:\Programas\Advertencia1.c 7 warning: 'i' is used uninitialized
in this function [-Wuninitialized]
Compare essa mensagem de advertncia com a mensagem de erro apresentada co-
mo exemplo na Seo 3.18.3 e note que, em termos de formato e contedo, a diferena
entre as duas mensagens a presena da palavra warning nessa ltima mensagem. A
ltima expresso entre colchetes que acompanha uma mensagem de advertncia indi-
ca a razo pela qual a mensagem de advertncia foi emitida. Nesse exemplo especfco,
a expresso: -Wuninitialized indica que a mensagem foi apresentada por causa do
Lidando com Erros de Sintaxe e Advertncias | 153
uso dessa opo de compilao que foi, implicitamente, includa em virtude do uso da
opo Wall, que incorpora todas as opes de advertncia.
Nessa situao, o compilador no detectou nenhum erro no seu programa, mas
emitiu uma mensagem de advertncia que prenuncia que algo grave pode acontecer
quando o programa for executado. No caso especfco do ltimo exemplo, o compi-
lador informa que o contedo da varivel i usado sem que lhe tenha sido atribudo
nenhum valor. Esse tipo de mensagem est sempre associado a um problema que se
manifestar quando o programa for executado. Para constatar o que foi afrmado, exe-
cute o programa e veja o que acontece.
Numa sesso de execuo do programa em discusso o resultado obtido foi:
i = 2147332096
Mas, o resultado poderia ter sido qualquer outro, visto que, como a varivel i no
foi iniciada, o espao em memria que ela representa indefnido.
Exemplo 2
Nem toda mensagem de advertncia antecipa um problema grave que possa ocorrer
durante a execuo de um programa, como foi o caso no exemplo precedente. Por
exemplo, considere agora o seguinte arquivo-fonte cujo nome Advertencia2.c.
#include <stdio.h>
int main(void)
{
int i = 10, j;
printf( "i = %d\n", i);
return 0;
}
Esse ltimo programa semelhante ao anterior, mas a fonte da mensagem de ad-
vertncia anterior foi corrigida com a iniciao da varivel i e foi acrescentada mais
uma varivel denominada j. Quando esse ltimo programa compilado com o com-
pilador GCC usando a opo Wall, ele emite a seguinte mensagem de advertncia:
C:\Programas\Advertencia2.c: In function 'main':
C:\Programas\Advertencia2.c 5 warning: unused variable 'j'
[-Wunused-variable]
Essa mensagem de advertncia alerta o programador para o fato de a varivel j
ter sido defnida, mas no ter sido usada. Diferentemente do problema indicado pela
mensagem de advertncia anterior, o problema indicado por meio da ltima mensagem
de advertncia no causa danos graves durante a execuo do programa (mas, causa um
pequeno desperdcio de memria).
Exemplo 3
Algumas verses antigas do compilador GCC podem apresentar a seguinte mensagem
de advertncia:
no newline at end of file
Essa mensagem rara e signifca que o arquivo-fonte no termina com uma linha
em branco. Voc pode resolver essa peitica acrescentando uma linha em branco ao fnal
do arquivo ou apenas ignor-la.
154 | Captulo 3 Introduo Linguagem C
Interpretando Mensagens de Advertncia
Resumindo o que foi discutido nesta seo, uma mensagem de advertncia pode alertar
o programador em relao a:
Um erro grave que ocorrer quando o programa for executado (primeiro
exemplo).
Uma m utilizao de recursos computacionais (segundo exemplo).
Um fato absolutamente irrelevante (terceiro exemplo).
Uma situao normal, mas que pode constituir um erro grave num contexto
diferente. Por exemplo, o uso de um operador de atribuio num local onde,
tipicamente, deveria ser utilizado um operador de igualdade (exemplos con-
cretos dessa natureza sero apresentados no Captulo 8).
Como se pode ver, h vrias interpretaes para mensagens de advertncias, mas, in-
dependentemente desse fato, as recomendaes a seguir devem ser seguidas rigorosamente:
Use sempre a opo que faz com que o compilador emita o maior nmero
possvel de mensagens de advertncia. No caso do compilador GCC, essa
opo Wall.
Nunca deixe de dar a devida ateno a uma mensagem de advertncia.
3.18.5 Mensagens de Erro e Advertncia Combinadas
Existem mais quatro observaes importantes em relao a mensagens de erro e
advertncia:
Um nico erro de sintaxe pode originar mais de uma mensagem de erro.
Um erro de sintaxe pode originar, alm de uma mensagem de erro, uma
mensagem de advertncia.
Uma instruo sintaticamente correta que pode originar uma mensagem
de advertncia nunca capaz de dar origem a uma mensagem de erro.
O primeiro erro apontado pelo compilador sempre um erro real, mas er-
ros subsequentes podem no corresponder a outros erros legtimos. Isto ,
esses erros subsequentes podem ser apontados em consequncia da ocor-
rncia do primeiro erro detectado pelo compilador.
Portanto, baseado nessas premissas, quando deparado com uma combinao de
mensagens de erro, o programador deve primeiro tentar corrigir a instruo que deu
origem primeira mensagem de erro. Ento, em vez de tentar resolver as demais men-
sagens de erro, ele deve recompilar o programa para verifcar se as demais mensagens
de erro ainda persistem. Se ocorrerem combinaes de mensagens de erro e advertn-
cia, deve-se empregar o mesmo raciocnio, sempre dando ateno a mensagens de erro
antes das mensagens de advertncia.
Considere o seguinte programa como mais um exemplo:
Lidando com Erros de Sintaxe e Advertncias | 155
#include <stdio.h>
int main(void)
{
int i = 10
printf( "i = %d\n", i);
return 0;
}
Esse programa contm apenas um erro de sintaxe, que a ausncia de ponto e
vrgula ao fnal da defnio da varivel i. Quando se tenta compilar esse programa
usando GCC com a opo Wall, esse compilador apresenta as seguintes mensagens
(o nome do programa-fonte Erro2.c):
C:\Programas\Erro2.c: In function 'main':
C:\Programas\Erro2.c 7 error: expected ',' or ';' before 'printf'|
C:\Programas\Erro2.c 5 warning: unused variable 'i'
[-Wunused-variable]
Assim, de acordo com o diagnstico apresentado pelo compilador h uma mensa-
gem de erro e outra de advertncia. A mensagem de erro assinala corretamente o erro
de sintaxe, mas a mensagem de advertncia no faz jus ao programa, pois ela informa
que a varivel i foi defnida, mas no foi usada. Porm, o que ocorreu na realidade foi
que a instruo printf(), que usa a varivel i, no foi compilada em virtude do erro
de sintaxe. Se for efetuada a correo da instruo que originou a mensagem de erro,
quando o programa for recompilado, nenhuma das duas mensagens ser emitida.
3.18.6 Erros de Ligao
Erros de ligao so frequentemente confundidos com erros de compilao. Mas, um
erro de ligao apontado pelo linker e no pelo compilador. Os erros de ligao mais
comuns so causados pelas seguintes situaes:
1. O linker conseguiu efetuar todas as ligaes necessrias, mas, em virtude de a
alguma restrio imposta pelo sistema operacional, no conseguiu criar o ar-
quivo executvel que deveria resultar do processo de ligao.
2. Um programa usa uma funo de biblioteca que o linker no consegue encon-
trar porque o programador no lhe informou onde encontr-la.
Impossibilidade de Criao de Programa Executvel
O primeiro tipo de erro de ligao mencionado o mais comum e mais fcil de ser
resolvido. Ele ocorre principalmente durante a fase de testes de um programa quando
se realiza alguma alterao necessria no programa e tenta-se reconstruir o programa
executvel esquecendo-se que ele ainda est sendo executado. Nesse caso, o linker GCC
emite a seguinte mensagem:
Permission denied
ld returned 1 exit status
Observe que o formato dessa mensagem de erro bem diferente daquelas apre-
sentadas quando o compilador encontra um erro de sintaxe (v. Seo 3.18.3). A pri-
meira linha dessa mensagem:
Permission denied
156 | Captulo 3 Introduo Linguagem C
informa o programador que o linker no obteve permisso para criar o arquivo execut-
vel, muito provavelmente porque um arquivo executvel com o mesmo nome daquele
que se tenta criar encontra-se correntemente em uso. A ocorrncia desse tipo de erro
pouco provvel quando se usa ligao via linha de comando, mas muito comum
quando se utiliza um IDE. Para simular esse tipo de erro, abra o arquivo-fonte a seguir
usando CodeBlocks:
#include <stdio.h> /* printf() */
#include "leitura.h" /* LeituraFacil */
int main(void)
{
int i;
printf("\nDigite um inteiro: ");
i = LeInteiro();
printf("\nNumero inteiro digitado: %d", i);
return 0;
}
Ento, construa um programa executvel (v. Seo 3.17.5), abra uma janela de
terminal no diretrio onde se encontra o programa e comece a execut-lo. Suponha
que, no instante em que o programa apresenta o prompt:
Digite um inteiro:
voc decide que seria melhor que o prompt inclusse a palavra numero antes de intei-
ro. Ento, voc retorna ao editor de programas, altera a primeira instruo printf()
que contm esse prompt, salva o arquivo e tenta reconstruir o programa executvel.
Acontece que voc esqueceu que a ltima verso do arquivo executvel est em exe-
cuo e, quando o linker tenta sobrescrev-lo, o sistema operacional impede que isso
acontea. Enfm, voc presenteado com a referida mensagem de erro.
A segunda linha da aludida mensagem:
ld returned 1 exit status
pode ser um tanto redundante, mas bastante instrutiva em virtude dos seguintes
aspectos:
Essa mensagem comea com ld, que o nome ofcial do linker GCC. Portanto,
habitue-se ao fato de toda mensagem de erro contendo ld estar associada ao
uso do linker e ser, assim, um erro de ligao, e no de compilao.
O restante da linha informa que ld (i.e., o linker) retornou 1. Conforme foi
visto na Seo 3.17.1, um programa retorna um valor diferente de zero quan-
do ocorre algum problema que impede seu funcionamento normal. Nesse caso
especfco, o funcionamento normal de um linker produzir um programa
executvel.
Linker No Encontra Biblioteca
Observao: Se voc confgurou seu ambiente de desenvolvimento conforme reco-
mendado no Captulo 1 e usa as prescries para obteno de um arquivo executvel
apresentadas naquele e no presente captulo, o tipo de erro descrito nesta seo prova-
velmente no ocorrer. Portanto, continue lendo esta seo apenas se estiver interessado
em conhecer o funcionamento de um linker em maior profundidade.
Lidando com Erros de Sintaxe e Advertncias | 157
Para ilustrar o segundo tipo de erro comum de ligao mencionado, considere o
seguinte programa, cujo nome do arquivo-fonte ErroLigacao.c:
#include <stdio.h> /* printf() */
#include "leitura.h" /* LeituraFacil */
int main(void)
{
int i;
printf("\nDigite um numero inteiro: ");
i = LeInteiro();
printf("\nNumero inteiro digitado: %d", i);
return 0;
}
Do ponto de vista sinttico, esse programa est perfeitamente correto e voc po-
der comprovar essa afrmao compilando-o (literalmente) com a seguinte invocao
do compilador GCC digitada na linha de comando do sistema operacional:
gcc -c ErroLigacao.c
Invocado com a opo c, o compilador GCC apenas compila (literalmente) o progra-
ma-fonte, criando o respectivo arquivo-objeto, mas no invoca o linker para efetuar as
devidas ligaes e, assim, criar o arquivo executvel correspondente. Como o progra-
ma no contm nenhum erro sinttico, com a invocao acima, o compilador bem
sucedido em sua tarefa e cria o arquivo-objeto ErroLigacao.o.
Quando o compilador GCC invocado com a opo o, ele entende que a in-
teno do programador criar um programa executvel. Nesse caso, se o arquivo a ser
processado for um arquivo-fonte, ele ser compilado e, em seguida, ter suas ligaes
efetuadas. Por outro lado, se o arquivo a ser processado for um arquivo-objeto, apenas
as ligaes necessrias sero efetuadas. Assim, quando o linker GCC invocado com a
opo o, como a seguir, para efetuar as ligaes do arquivo-objeto ErroLigacao.o:
gcc ErroLigacao.o -o ErroLigacao.exe
ele apresenta as seguintes mensagens de erro:
ErroLigacao.o:ErroLigacao.c:(.text+0x1b): undefined reference to
'LeInteiro'
collect2: ld returned 1 exit status
A primeira dessas mensagens informa que, no cdigo objeto ErroLigacao.o, que
teve origem no arquivo-fonte ErroLigacao.c, foi encontrada uma chamada da funo
LeInteiro(). Entretanto, o linker no conseguiu encontrar a biblioteca (arquivo-ob-
jeto) que contm tal funo nem ele foi programado com essa informao. Quer dizer,
o linker no precisa ser informado sobre o local onde se encontram os arquivos-objeto
que fazem parte da biblioteca padro, desde que tanto essa biblioteca quanto o compi-
lador e o linker faam parte de uma mesma cadeia de ferramentas de desenvolvimento
(v. Seo 1.6.2). Em qualquer outra circunstncia, o linker precisa ser informado sobre
o paradeiro das bibliotecas necessrias. A forma mais fcil de prover essa informao
por meio da opo l seguida do nome do arquivo-objeto de biblioteca sem extenso,
como no seguinte comando:
gcc ErroLigacao.c -lleitura -o ErroLigacao.exe
Entretanto, para esse ltimo comando funcionar, as seguintes regras devem ser
satisfeitas:
158 | Captulo 3 Introduo Linguagem C
O nome da biblioteca deve comear com lib e ter extenso .a, como, por
exemplo, libLeitura.a.
O arquivo de biblioteca deve jazer num diretrio onde o linker costuma encon-
trar arquivos de biblioteca (p. ex., o diretrio /usr/local/lib/ no Linux).
Existem outras maneiras de fazer com que um linker encontre uma biblioteca ne-
cessria para a construo de um programa executvel. Mas, esse tpico est alm do
escopo deste livro.
3.18.7 Prtica: Cometendo Erros Voluntariamente
Uma tima maneira de aprender a lidar com erros de programao comet-los inten-
cionalmente e, para cada erro, verifcar como o compilador responde. Para tal aprendi-
zado, use programas bem simples, como os exemplifcados a seguir e acrescente erros
um-a-um. Familiarizando-se desse modo com erros, voc estar mais apto a lidar com
eles na vida real; i.e., quando eles forem acidentais e no propositais.
Prtica de Erros 1
Considere o seguinte programa:
#include <stdio.h>
int main(void)
{
int x = 10, y = 2;
printf("x/y = %d", x/y);
}
Esse programa bastante simples e livre de erros de sintaxe. Assim, a prtica con-
sistir em introduzir erros nesse programa e, para cada erro inserido, preencher as se-
guintes informaes:
Erro: [descreva aqui o erro introduzido voluntariamente no programa]
Mensagem: [copie aqui a mensagem de erro ou advertncia apresentada pelo
compilador. Para melhorar o entendimento acrescente (E) se a mensagem for
de erro e (A) se a mensagem for de advertncia]
Consequncia: [apresente aqui qual a consequncia do erro. Evidentemente,
se o erro introduzido no programa for de sintaxe, a consequncia que ele no
compila. Se a mensagem emitida pelo compilador for de advertncia execute
o programa e verifque qual o resultado.]
Por exemplo, usando o programa acima e o modelo de experimento proposto,
pode-se inserir um ponto e vrgula indevido ao fnal da diretiva #include e preencher
as respectivas informaes como:
Erro: Ponto e vrgula ao fnal da diretiva #include.
Mensagem: (A) C:\Programas\Erros1.c 1 warning: extra tokens at
end of #include directive [enabled by default]
Consequncia: nenhuma
Depois de satisfeitos os propsitos da introduo de um erro e antes de passar para
o erro seguinte, o programa deve ser corrigido de volta ao seu estado inicial.
Exerccios. Seguindo o modelo de atividade prtica proposta, introduza os erros des-
critos a seguir e faa as devidas anotaes.
1. Remova os parnteses da funo main().
Exemplos de Programao | 159
2. Remova o ponto e vrgula que acompanha a defnio de variveis.
3. Substitua vrgula por ponto e vrgula na defnio de variveis.
4. Remova as aspas da direita do string de printf().
5. Remova as duas aspas do string de printf().
6. Substitua as aspas do string de printf() por apstrofos.
7. Substitua %d por %f em printf().
8. Remova o abre-chaves na linha seguinte quela contendo main().
9. Substitua { por } na linha seguinte quela contendo main().
10. Remova o fecha-chaves ao fnal da funo main().
11. Remova a linha contendo return.
Prtica de Erros 2
Para uma segunda atividade prtica, considere o seguinte programa:
#include <stdio.h>
#define PI 3.14
int main(void)
{
double raio = 1.0, area;
/* Calcula a rea do crculo */
area = 2*PI*raio;
printf("Area = %f", area);
return 0;
}
Exerccio. Siga o modelo da atividade prtica anterior e introduza nesse programa os
erros descritos a seguir:
1. Remova o fechamento de comentrio (i.e., */).
2. Acrescente ponto e vrgula ao fnal da diretiva #defne.
3. Coloque um fecha-parnteses adicional na chamada de printf().
4. Coloque um abre-parnteses adicional na chamada de printf().
5. Troque o especifcador de formato %f por %d em printf().
6. Troque o especifcador de formato %f por %s em printf().
7. Remova a iniciao da varivel raio.
Desafo: O ltimo programa, em seu estado original, no contm erro de sintaxe, visto
que ele compilado normalmente, nem erro de execuo, pois ele executado normal-
mente sem ser abortado. No entanto, esse programa contm um erro de lgica. Isto ,
ele apresenta um resultado que no satisfaz o bom senso. Qual esse erro?
3.19 Exemplos de Programao
3.19.1 Um Programa Robusto
Problema: Escreva um programa que l um nmero inteiro, um nmero real e um ca-
ractere, nessa ordem, usando as funes da biblioteca LeituraFacil. Aps cada leitura,
o programa deve exibir o valor lido na tela.
160 | Captulo 3 Introduo Linguagem C
Soluo:
Algoritmo
inteiro i, c
real f
escreva("Digite um numero inteiro:")
leia(i)
escreva("Numero inteiro digitado:", i)
escreva("Digite um numero real:")
leia(f)
escreva("Numero real digitado:", f)
escreva("Digite um caractere")
leia(c)
escreva("Caractere digitado:", c)
Programa
#include <stdio.h> /* Entrada e sada */
#include "leitura.h" /* LeituraFacil */
/****
* main(): L corretamente um nmero inteiro, um nmero real
* e um caractere e apresenta-os na tela.
*
* Parmetros: Nenhum
*
* Retorno: Zero
****/
int main(void)
{
int i, c;
double f;
/* Apresenta o programa */
printf( "\n\t>>> Este programa mostra como deve"
"\n\t>>> ser um programa robusto.\n" );
printf("\n\t>>> Digite um numero inteiro > ");
i = LeInteiro();
printf("\n>> Numero inteiro digitado: %d\n", i);
printf("\n\t>>> Digite um numero real > ");
f = LeReal();
printf("\n>> Numero real digitado: %f\n", f);
printf("\n\t>>> Digite um caractere > ");
c = LeCaractere();
printf("\n>> Caractere digitado: %c\n", c);
/* Despede-se do usurio */
printf( "\n\t>>> Obrigado por usar este programa.\n");
return 0;
}
Exemplo de execuo do programa:
Exemplos de Programao | 161
>>> Este programa mostra como deve
>>> ser um programa robusto.
>>> Digite um numero inteiro > abc
>>> O valor digitado e' invalido. Tente novamente
> -12
>> Numero inteiro digitado: -12
>>> Digite um numero real > x2.5
>>> O valor digitado e' invalido. Tente novamente
> 2.5x
>>> 1 caractere foi descartado
>> Numero real digitado: 2.500000
>>> Digite um caractere > xyz
>>> 2 caracteres foram descartados
>> Caractere digitado: x
>>> Obrigado por usar este programa.
3.19.2 Um Programa Melindroso
Problema: Escreva um programa que l um nmero inteiro, um nmero real e um
caractere, nessa ordem, usando as funes do mdulo stdio da biblioteca padro de C.
Aps cada leitura, o programa deve apresentar o valor lido na tela.
Soluo:
Algoritmo: A soluo para esse problema segue o mesmo algoritmo do exemplo
apresentado na Seo 3.19.1.
Programa
#include <stdio.h> /* Entrada e sada */
/****
* main(): Tenta ler usando scanf() um nmero inteiro,
* um nmero real e um caractere e apresenta
* o resultado da leitura na tela.
*
* Parmetros: Nenhum
*
* Retorno: Zero
****/
int main(void)
{
int i, c;
double f;
/* Apresenta o programa */
printf( "\n\t>>> Este programa e' fragil como"
"\n\t>>> alfeni. Trate-o com carinho.\n" );
printf("\n\t>>> Digite um numero inteiro > ");
scanf("%d", &i);
printf("\n>> Numero inteiro digitado: %d\n", i);
printf("\n\t>>> Digite um numero real > ");
162 | Captulo 3 Introduo Linguagem C
scanf("%lf", &f);
printf("\n>> Numero real digitado: %f\n", f);
printf("\n\t>>> Digite um caractere > ");
c = getchar();
printf("\n>> Caractere digitado: %c\n", c);
/* Despede-se do usurio */
printf( "\n\t>>> Obrigado por usar este programa.\n");
return 0;
}
Exemplos de execuo do programa:
Exemplo 1 [usurio mal comportado ou defciente cognitivo]:
>>> Este programa e' fragil como
>>> alfeni. Trate-o com carinho.
>>> Digite um numero inteiro > abc
>> Numero inteiro digitado: 0
>>> Digite um numero real >
>> Numero real digitado: 0.000000
>>> Digite um caractere >
>> Caractere digitado: a
>>> Obrigado por usar este programa.
Exemplo 2 [usurio bem comportado e esperto]:
>>> Este programa e' fragil como
>>> alfeni. Trate-o com carinho.
>>> Digite um numero inteiro > -12
>> Numero inteiro digitado: -12
>>> Digite um numero real > 2.54
>> Numero real digitado: 2.540000
>>> Digite um caractere >
>> Caractere digitado:
>>> Obrigado por usar este programa.
Anlise: Compare esse programa com aquele apresentado na Seo 3.19.1 e note que
esse programa no funciona adequadamente nem quando o usurio bem comportado.
Voc entender melhor os problemas do programa acima na Seo 10.9.
3.19.3 Separando um Inteiro em Centena, Dezena e Unidade
Problema: Escreva um programa que l um nmero inteiro de trs dgitos e separa-o
em centena, dezena e unidade.
Soluo:
Algoritmo
inteiro n, resto
Exemplos de Programao | 163
escreva("Digite um numero inteiro de trs dgitos:")
leia(n)
escreva("Centena:", n/100)
resto n%100
escreva("Dezena:", resto/10)
escreva("Unidade:", resto%10)
Programa
#include <stdio.h> /* printf() */
#include "leitura.h" /* LeituraFacil */
/****
* main(): Separa um nmero inteiro introduzido via
* teclado em centena, dezena e unidade
*
* Parmetros: Nenhum
*
* Retorno: Zero
****/
int main(void)
{
int n, resto;
/* Apresenta o programa */
printf( "\n\t>>> Este programa le um numero inteiro"
"\n\t>>> de tres digitos e separa-o em "
"\n\t>>> centena, dezena e unidade.\n" );
/* L o nmero */
printf("\nDigite um numero inteiro de tres digitos: ");
n = LeInteiro();
/* Exibe a centena */
printf("\n\t>>> Centena: %d", n/100);
/* Descarta a centena */
resto = n%100;
/* Exibe a dezena */
printf("\n\t>>> Dezena: %d", resto/10);
/* Exibe a unidade */
printf("\n\t>>> Unidade: %d\n", resto%10);
return 0;
}
Anlise: Os comentrios inseridos no programa devem ser sufcientes para seu
entendimento.
Exemplo de execuo do programa:
>>> Este programa le um numero inteiro
>>> de tres digitos e separa-o em
>>> centena, dezena e unidade.
Digite um numero inteiro de tres digitos: 543
>>> Centena: 5
>>> Dezena: 4
164 | Captulo 3 Introduo Linguagem C
>>> Unidade: 3
3.19.4 Alinhamento de Inteiros na Tela
Problema: Escreva um programa que mostra como alinhar inteiros direita ou es-
querda na tela usando printf() com os especifcadores de formato %nd e %-nd, onde
n um valor inteiro positivo.
Soluo:
Algoritmo: A soluo desse problema envolve apenas chamadas da funo printf().
Portanto, o algoritmo a ser seguido to trivial que torna-se desnecessrio apresent-lo.
Programa
#include <stdio.h> /* Entrada e sada */
/****
* main(): Alinha inteiros esquerda e direita na tela
* usando os especificadores %nd e %-nd de printf()
*
* Parmetros: Nenhum
*
* Retorno: Zero
****/
int main(void)
{
int n1 = 1,
n2 = 12,
n3 = 123,
n4 = 1234;
/* Apresenta o programa */
printf( "\n\t>>> Este programa alinha numeros inteiros "
"na tela\n" );
/* Alinhamento direita */
printf("\n%5d\n", n1);
printf("%5d\n", n2);
printf("%5d\n", n3);
printf("%5d\n", n4);
/* Alinhamento esquerda */
printf("\n%-5d\n", n1);
printf("%-5d\n", n2);
printf("%-5d\n", n3);
printf("%-5d\n", n4);
/* Alinhamento direita e esquerda */
printf("\n%5d\t%-5d\n", n1, n1);
printf("%5d\t%-5d\n", n2, n2);
printf("%5d\t%-5d\n", n3, n3);
printf("%5d\t%-5d\n", n4, n4);
return 0;
}
Quando executado o programa apresenta o seguinte na tela:
>>> Este programa alinha numeros inteiros na tela
1
Exemplos de Programao | 165
12
123
1234
1
12
123
1234
1 1
12 12
123 123
1234 1234
Anlise: O alinhamento de nmeros apresentado pelo programa obtido por meio do
especifcador %nd, onde n um inteiro positivo ou negativo. Quando o valor de n
positivo, o alinhamento direita; quando n negativo, o alinhamento d-se esquerda.
3.19.5 Multiplicando Duas Fraes
Problema: Escreva um programa que multiplica duas fraes. Cada frao lida como
dois nmeros inteiros: o primeiro representa o numerador e o segundo o denominador
da funo. Ento, o programa calcula o produto e apresenta o resultado.
Soluo:
Algoritmo
inteiro n1, d1, n2, d2
escreva("Digite o numerador da primeira frao:")
leia(n1)
escreva("Digite o denominador da primeira frao:")
leia(d1)
escreva("Digite o numerador da segunda frao:")
leia(n2)
escreva("Digite o denominador da segunda frao:")
leia(d2)
escreva("Resultado:", n1, "/", d1, " * ", n2, "/", d2, "=",
n1*n2, "/", d1*d2, "=", (n1*n2)/(d1*d2) );
Programa
/****
* main(): L e multiplica duas fraes
*
* Parmetros: Nenhum
*
* Retorno: Zero
****/
int main(void)
{
int n1, d1, /* Numerador e denominador da */
n2, d2; /* primeira e da segunda fraes */
/* Apresenta o programa */
printf("\n\t>>> Este programa multiplica duas fracoes.\n");
printf("\nDigite o numerador da primeira fracao: ");
166 | Captulo 3 Introduo Linguagem C
n1 = LeInteiro();
printf("\nDigite o denominador da primeira fracao: ");
d1 = LeInteiro();
printf("\nDigite o numerador da segunda fracao: ");
n2 = LeInteiro();
printf("\nDigite o denominador da segunda fracao: ");
d2 = LeInteiro();
printf( "\nResultado: %d/%d * %d/%d = %d/%d = %3.2f\n",
n1, d1, n2, d2, n1*n2, d1*d2,
(double) (n1*n2)/(d1*d2) );
return 0;
}
Exemplo de execuo do programa:
>>> Este programa multiplica duas fracoes
Digite o numerador da primeira fracao: 2
Digite o denominador da primeira fracao: 3
Digite o numerador da segunda fracao: 5
Digite o denominador da segunda fracao: 7
Resultado: 2/3 * 5/7 = 10/21 = 0.48
Anlise: O ltimo programa bastante simples, mas merece um comentrio impor-
tante. Se qualquer dos nmeros que representam os denominadores das fraes for ze-
ro, o programa ser abortado. No prximo captulo, voc aprender como precaver-se
contra esse percalo.
3.20 Exerccios de Reviso
A Linguagem C (Seo 3.1)
1. (a) O que padronizao de uma linguagem? (b) Por que um padro de lingua-
gem desejvel?
2. (a) O que o padro ISO da linguagem C? (b) Como popularmente conhecido
o padro corrente da linguagem C?
3. O signifca dizer que uma caracterstica de C dependente de implementao?
4. Uma questo de reconhecimento de valor: quem criou a linguagem C?
Identifcadores (Seo 3.2)
5. Quais so as regras para formao de identifcadores de C?
6. (a) O que so palavras-chave? (b) Uma varivel pode ter o nome de uma palavra-chave?
7. (a) O que so palavras reservadas? (b) Uma varivel pode ter o nome de uma pa-
lavra reservada?
8. Um programa em C pode ser escrito usando apenas letras maisculas?
9. Quais dos seguintes nomes no podem ser utilizados como identifcadores em C?
Explique por que.
Exerccios de Reviso | 167
(a) var (c) int (d) $a e) a$
(g) double (i) VOID (j) void (l) _10
Cdigos de Caracteres (Seo 3.3)
10. Em linhas gerais, qual o contedo do conjunto bsico de caracteres da linguagem C?
11. (a) O que um cdigo de caracteres? (b) Apresente trs exemplos de cdigos de
caracteres.
12. Como caracteres so representados na memria de um computador?
13. Seja a uma varivel do tipo char. Suponha que o cdigo de caracteres ASCII seja
utilizado. Que valor inteiro (em base decimal) ser armazenado em a aps a exe-
cuo de cada uma das seguintes instrues:
(a) a = 'G'; (b) a = 9; (c) a = '9'; (d) a = '1' + '9';
[Sugesto: Consulte uma tabela do cdigo ASCII fartamente encontrada na internet.]
14. Suponha que c seja uma varivel do tipo char. As atribuies c = 'A' e c = 65
so equivalentes?
Tipos de Dados Primitivos (Seo 3.4)
15. (a) O que um tipo de dado? (b) O que um tipo de dado primitivo de uma lin-
guagem de programao?
16. Descreva os seguintes tipos primitivos da linguagem C:
(a) int
(b) char
(c) double
Constantes (Seo 3.5)
17. Quais so os dois formatos de escrita de constantes reais?
18. (a) O que uma sequncia de escape? (b) Em que situaes sequncias de escape
se fazem necessrias? (c) Apresente trs exemplos de sequncias de escape.
19. As sequncias de escape '\n' e '\t' so as mais usadas em escrita na tela. Qual
o efeito de cada uma delas?
20. (a) O que um string constante? (b) Qual a diferena entre string constante e
caractere constante?
21. (a) Quando um string constante muito extenso, como ele pode ser separado em
partes? (b) Qual a vantagem que essa facilidade oferece para o programador?
22. Uma sequncia de escape pode ser inserida num string constante?
23. (a) A expresso 'A' + 'B' legal? Explique. (b) Em caso afrmativo, essa expresso
tem algum signifcado prtico? (b) Pegadinha: qual o resultado dessa expresso?
24. Outra pegadinha: qual o resultado de 'Z' - 'A'? [Dica: H garantia de que
todas as letras sejam contguas num cdigo de caracteres?]
25. (a) Qual o resultado de '9' - '0' (no pegadinha)? (b) Qual o resultado de
'2' - '0'? (c) Em geral, o que signifca uma expresso do tipo dgito '0'?
168 | Captulo 3 Introduo Linguagem C
26. Como classifcada cada uma das seguintes constantes:
(a) 10 (b) 3.14 (c) 1.6e10 (d) '\n' (e) "A"
Propriedades dos Operadores da Linguagem C (Seo 3.6)
27. (a) Dentre os operadores apresentados neste captulo, qual deles tem a maior pre-
cedncia? (b) Qual deles tem a menor precedncia?
28. (a) O que efeito colateral de um operador? (b) Quais so os operadores que pos-
suem efeito colateral apresentados neste captulo?
29. Dentre os operadores apresentados neste captulo, quais deles possuem ordem de
avaliao de operandos defnida?
30. A ordem de avaliao de um operador pode ser alterada por meio de parnteses?
31. Suponha que i e j sejam variveis do tipo int. Explique por que a instruo abaixo
no portvel (apesar de ser sintaticamente legal em C):
j = (i + 1) * (i = 1)
32. Quais so as precedncias relativas entre os operadores aritmticos, relacionais e
lgicos? Em outras palavras, considerando cada categoria de operadores como uma
unidade, qual dessas categorias tem maior, intermediria e menor precedncia?
Operadores e Expresses (Seo 3.7)
33. (a) O que um operador? (b) O que um operando? (c) O que uma expresso?
34. Calcule o resultado de cada uma das seguintes operaes inteiras:
(a) -20/3
(b) -20%3
(c) -20/-3
(d) -20%-3
(e) 20/-3
(f ) 20%-3
35. (a) O que um operador relacional? (b) Quais so os operadores relacionais de C?
36. Em que diferem os operadores relacionais apresentados no Captulo 2 e os ope-
radores relacionais de C?
37. Quais so os possveis resultados de aplicao de um operador relacional?
38. Os operadores relacionais de C tm a mesma precedncia?
39. Assuma a existncia das seguintes defnies de variveis num programa em C:
int m = 5, n = 4;
double x = 2.5, y = 1.0;
Quais sero os valores das seguintes expresses?
(a) m + n + x - y
(b) m + x - (n + y)
(c) x - y + m + y / n
40. Aplique parnteses nas expresses abaixo que indiquem o modo como um progra-
ma executvel traduzido por um compilador de C efetuaria cada operao:
(a) a = b*c == 2
(b) a = b && x != y
Exerccios de Reviso | 169
(c) a = b = c + a
41. (a) O que um operador lgico? (b) Quais so os operadores lgicos de C? (c)
Quais so os possveis resultados da aplicao de um operador lgico?
42. O que tabela-verdade?
43. (a) Quais so as semelhanas entre os operadores lgicos da pseudolinguagem apre-
sentada no Captulo 2 e os operadores lgicos de C? (b) Quais so as diferenas
entre essas categorias de operadores?
44. (a) O que curto-circuito de um operador? (b) Quais operadores apresentam essa
propriedade?
45. Sejam x e y duas variveis do tipo int previamente defnidas. As expresses (1) e
(2) a seguir so equivalentes? Explique seu raciocnio.
(1) x > 0 || ++y < 10
(2) ++y < 10 || x > 0
46. Sejam x e y duas variveis do tipo int previamente defnidas. Por que um programa
contendo a expresso (1) a seguir pode ser abortado em decorrncia de sua avaliao,
mas o mesmo no ocorre se essa expresso for substituda pela expresso (2) abaixo?
(1) y%x && x > 0
(2) x > 0 && y%x
47. (a) Por que a expresso 1/3 + 1/3 + 1/3 no resulta em 1? (b) Qual o resul-
tado dessa expresso?
48. Suponha que x seja uma varivel do tipo int. Escreva expresses lgicas em C que
denotem as seguintes situaes:
(a) x maior do que 2, mas menor do que 10
(b) x divisvel por 2 ou 3
(c) x par, mas diferente de 6
(d) x igual a 2 ou 3 ou 5
49. Suponha que x e y sejam variveis do tipo int. (a) possvel determinar o resulta-
do da expresso (x = 0) && (y = 10) sem saber quais so os valores correntes
de x e y? (b) Se for possvel calcular esse resultado, qual ele?
50. Por que o programa a seguir escreve na tela: O valor de 2/3 e' 0.000000?
#include <stdio.h>
int main(void)
{
double produto = 2/3;
printf("O valor de 2/3 e' %f\n", produto);
return 0;
}
Defnies de Variveis (Seo 3.8)
51. O que uma defnio de varivel?
52. Que informao provida para o compilador por uma defnio de varivel?
53. Qual a utilidade de uma defnio de varivel?
170 | Captulo 3 Introduo Linguagem C
54. Por que importante usar convenes diferentes para escrita de identifcadores que
pertencem a categorias diferentes?
Operador de Atribuio (Seo 3.9)
55. Em que diferem os operadores = e ==?
56. Qual o valor atribudo varivel z na instruo de atribuio abaixo?
int x = 2, y = 5, z = 0;
z = x*y == 10;
57. Suponha que i seja uma varivel do tipo int e d seja uma varivel do tipo double.
Que valores sero atribudos a i e d nas instrues a seguir:
(a) d = i = 2.5;
(b) i = d = 2.5;
Converses de Tipos (Seo 3.10)
58. (a) O que converso implcita? (b) Por que s vezes ela necessria?
59. Em que situaes um compilador efetua converso implcita?
60. Cite alguns problemas decorrentes de converso implcita.
61. (a) Um computador capaz de realizar a operao 2 + 2.5 (i.e., a soma de um
nmero inteiro com um nmero real)? (b) permitido a escrita dessa expresso
num programa em C? (c) O resultado dessa operao inteira ou real?
62. (a) Para que serve o operador (double) na instruo de atribuio abaixo? (b) Ele
estritamente necessrio? (c) Existe alguma justifcativa para seu uso?
double x;
x = (double)2;
63. Suponha que x seja uma varivel do tipo double. Que valor atribudo a x em
cada uma das seguintes atribuies:
(a) x = 5/2;
(b) x = (double)5/2;
(c) x = (double)5/(double)2;
(d) x = (double)(5/2);
Incremento e Decremento (Seo 3.11)
64. (a) O que incremento? (b) O que decremento? (c) Quais so os operadores de
incremento e decremento?
65. Explique a diferena entre os operadores prefxo e sufxo de incremento.
66. Dadas as seguintes iniciaes:
int j = 0, m = 1, n = -1;
Quais sero os resultados de avaliao das seguintes expresses em C?
(a) m++ - --j
(b) m * m++ [O resultado dessa expresso dependente do compilador; apresente
os dois resultados possveis.]
67. O que exibe na tela cada um dos seguintes trechos de programa?
(a)
Exerccios de Reviso | 171
int x = 1;
printf("x++ = %d", x++);
(b)
int x = 1;
printf("++x = %d", ++x);
68. Seja x uma varivel do tipo int. O que h de errado com a expresso: ++(x + 1)?
69. Considere o seguinte trecho de programa:
int i, j = 4;
i = j * j++;
Mostre que, se a varivel j for avaliada primeiro, a expresso j * j++ resultar em
16 e, se a expresso j++ for avaliada primeiro, o resultado ser 20.
70. Suponha que soma e x sejam variveis do tipo int iniciadas com 0. A instruo a
seguir portvel? Explique.
soma = (x = 2) + (++x);
Comentrios (Seo 3.12)
71. (a) Como comentrios podem ser inseridos num programa? (b) Como um com-
pilador lida com comentrios encontrados num programa?
72. Por que comentrios so necessrios num programa?
73. Por que um programa sem comentrios compromete seu entendimento?
74. Qual o melhor momento para comentar um programa? Por qu?
75. Em que sentido comentrios num programa escrito por um programador profssional
no devem imitar comentrios encontrados em livros de ensino de programao?
76. Por que comentrios redundantes so quase to prejudiciais a um programa quanto
a ausncia de comentrios?
77. Que informaes mnimas deve conter um comentrio de bloco includo no in-
cio de um programa?
Bibliotecas (Seo 3.13)
78. No contexto de programao, o que uma biblioteca?
79. possvel programar utilizando uma linguagem de programao que no possui
biblioteca?
80. Como a biblioteca de uma linguagem de programao auxilia o programador?
81. (a) O que a biblioteca padro de C? (b) Por que funes dessa biblioteca no so
estritamente consideradas partes integrantes da linguagem C?
82. Por que se diz que a biblioteca padro de C um apndice dessa linguagem?
83. O que um arquivo de cabealho?
84. (a) Para que serve uma diretiva #include? (b) Como uma diretiva #include
processada?
85. Quando se faz necessrio incluir cada um dos seguintes cabealhos?
(a) stdio.h
(b) math.h
172 | Captulo 3 Introduo Linguagem C
(c) string.h
(d) leitura.h
86. Por que a incluso do cabealho stdio.h da biblioteca padro de C escrita como:
#include <stdio.h>
enquanto que a incluso do cabealho leitura.h da biblioteca LeituraFacil
escrita como:
#include "leitura.h"
Entrada via Teclado e Sada via Tela (Seo 3.14)
87. Teste seu conhecimento sobre a lngua portuguesa: qual a diferena entre os sig-
nifcados de interao e iterao?
88. (a) O que um programa interativo? (b) Apresente trs exemplos de programas
interativos. (c) Apresente dois exemplos de programas que no so interativos.
89. O que um programa robusto do ponto de vista de entrada de dados?
90. Descreva o funcionamento da funo printf().
91. O que um especifcador de formato?
92. (a) O que string de formatao? (b) O que pode conter um string de formatao
da funo printf()?
93. A que deve corresponder um especifcador de formato encontrado num string de
formatao numa chamada de printf()?
94. Suponha que voc tenha num programa a seguinte iniciao de varivel:
int c = 'A';
Usando a varivel c, como voc exibiria na tela: (a) o caractere 'A' e (b) o inteiro
associado a esse caractere no cdigo de caracteres utilizado.
95. Descreva o efeito de cada um dos seguintes especifcadores de formato de printf():
(a) %f
(b) %5.2f
(c) %5d
(d) %-5d
(e) %d
(f ) %c
(g) %s
96. Como voc produziria na tela: (a) uma quebra de linha e (b) um espao de tabulao?
97. Quando um nmero real escrito na tela com o uso de printf() com o especifca-
dor %f quantas casas decimais aparecem?
98. Suponha que o contedo de uma varivel x do tipo double seja 2.4569. O que
ser apresentado na tela quando cada uma das seguintes chamadas de printf() for
executada?
(a) printf("%f", x);
(b) printf("%d", x); [Pense bem antes de responder esse item]
(c) printf("%3.2f", x);
(d) printf("%4.2f", x);
Exerccios de Reviso | 173
99. O que apresenta na tela o seguinte programa?
#include <stdio.h>
int main(void)
{
int i = 43;
printf("%d\n", printf("%d", printf("%d",i)));
return 0;
}
100. Por que o programa a seguir no exibe o resultado esperado?
#include <stdio.h>
int main(void)
{
int resultado = 2 + 2;
printf("O resultado e': %d\n");
return 0;
}
101. O que programa a seguir exibe na tela?
#include <stdio.h>
int main(void)
{
int i = 6, j;
j = ++i < 7 && i++/6 || ++i <= 9;
printf("\ni = %d, j = %d\n", i, j);
return 0;
}
102. O que programa a seguir escreve na tela?
#include <stdio.h>
int main(void)
{
printf("1/3 = %f\n", 1/3);
return 0;
}
103. O que prompt e qual sua importncia num programa interativo?
104. Critique os seguintes prompts apresentados para um usurio comum de um
programa:
(a) Digite um string
(b) Tecle ^C para encerrar o programa
105. Por que a ausncia de prompt ou a apresentao de um prompt incorreto pode
ser responsvel por erros num programa?
106. Por que o programa a seguir no exibe o resultado esperado?
#include <stdio.h>
int main(void)
{
174 | Captulo 3 Introduo Linguagem C
double resultado;
resultado = 21.0 / 7.0;
printf("Resultado da divisao: %d\n", resultado);
return 0;
}
Constantes Simblicas (Seo 3.15)
107. (a) O que uma constante simblica? (b) Como uma constante simblica defnida?
108. (a) Por que no se deve terminar uma defnio de constante simblica com ponto
e vrgula? (b) Por que um programador iniciante tem difculdade em detectar esse
tipo de erro? (c) Como o uso de convenes diferentes para escrita de identifca-
dores que pertencem a categorias diferentes facilita a deteco desse tipo de erro?
109. Que vantagens so advindas do uso de constantes simblicas num programa?
110. Como se declara uma constante simblica em linguagem algortmica?
Como Construir um Programa II: Implementao (Seo 3.16)
111. Quais so os passos envolvidos na construo de um programa de pequeno porte
numa linguagem algortmica?
Programas Monoarquivos em C (Seo 3.17)
112. verdade que todo programa em C deve necessariamente ter uma funo deno-
minada main?
113. (a) O que um sistema com hospedeiro? (b) O que um sistema livre?
114. O que um programa de console?
115. Como o esboo de um programa monoarquivo simples em C?
116. (a) O que signifca main num programa em C? (b) Por que todo programa com
hospedeiro em C precisa incluir uma funo main()? (c) Esse nome pode ser
alterado?
117. Qual o signifcado da instruo return 0; encontrada em programas em C?
118. O programa a seguir legal em C?
int main(void)
{
(1 + 2) * 4;
return 0;
}
119. (a) Que smbolo usado como terminal de instruo? (b) Toda linha de um pro-
grama em C termina com esse smbolo?
120. Qual a diferena entre teste e depurao de um programa?
Lidando com Erros de Sintaxe e Advertncias (Seo 3.18)
121. Qual a diferena entre mensagem de erro e mensagem de advertncia emitida
por um compilador?
122. (a) O que um erro sinttico ou de compilao? (b) O que um erro de execu-
o? (c) O que um erro lgico? (d) Qual deles o mais fcil de ser consertado?
Exerccios de Programao | 175
(e) Qual deles o mais difcil de ser consertado? [Voc aprender mais sobre esse
tpico no Captulo 6.]
123. Apresente cinco erros sintticos comuns.
124. Apresente dois erros de execuo comuns.
125. Por que no recomendvel ignorar uma mensagem de advertncia?
126. O que h de errado com o seguinte programa?
#include <stdio.h>
#include "leitura.h"
int main(void)
{
int x;
printf("\nDigite um numero inteiro: ");
x = LeInteiro();
printf("\n100/%d = %d\n", x, 100/x);
return 0;
}
3.21 Exerccios de Programao
3.21.1 Fcil
EP3.1) Escreva um programa em C que exibe o seguinte na tela:
Meu nome e' [apresente aqui seu nome]
Sou [aluno ou aluna] do curso [nome do curso]
Digite um caractere seguido de ENTER para encerrar o
programa:
Esse programa dever apresentar os contedos entre colchetes substitudos
adequadamente e s dever ter sua execuo encerrada quando o usurio digitar
algum caractere seguido de [ENTER]. [Sugesto: Use a funo LeCaractere()
para ler o caractere que corresponde tecla digitada pelo usurio.]
EP3.2) Escreva um programa que leia valores inteiros representando numeradores e
denominadores de duas funes, calcula a soma das duas fraes e apresenta
o resultado na tela. [Sugesto: v. exemplo apresentado na Seo 3.19.5.]
EP3.3) Escreva um programa que l dois valores reais representando os lados de
um retngulo numa dada unidade de comprimento e exibe na tela a rea,
o permetro e a diagonal do retngulo. [Sugesto: O permetro dado por
2*(L1 + L2); a rea dada por L1*L2 e a diagonal dada por sqrt(L1*L1
+ L2*L2), onde L1 e L2 so os lados do retngulo.]
EP3.4) Escreva um programa que l trs nmeros inteiros digitados pelo usurio.
Ento, o programa apresenta na tela a soma, o produto e a mdia dos nme-
ros introduzidos.
EP3.5) Escreva um programa que l um nmero inteiro com quatro dgitos intro-
duzido pelo usurio e apresenta na tela, em linhas separadas, a milhar, a
176 | Captulo 3 Introduo Linguagem C
centena, a dezena e a unidade do nmero. [Sugesto: v. exemplo apresenta-
do na Seo 3.19.3.]
EP3.6) Escreva um programa que calcula o gasto mensal de gasolina do usurio e
apresenta o resultado. A interao desse programa com o usurio exempli-
fcada a seguir:
Quantos quilometros por dia voce dirige? 35
Quantos dias por semana voce dirige? 6
Quantos quilometros por litro seu carro faz? 15
Qual e' o preco do litro da gasolina (R$)? 2.71
>>> Gasto mensal de gasolina: R$37.94
EP3.7) Escreva um programa que calcula o volume de um cone circular reto de acor-
do com a frmula:
v = *r
2
*h/3
onde v o volume, r o raio e h a altura do cone. A seguir, um exemplo
de execuo desse programa:
Este programa calcula o volume de um cone circular reto
Introduza o raio (cm): 2.5
Introduza a altura (cm): 9.2
>>> Volume do cone: 60,18 cm3
3.21.2 Moderado
EP3.8) O programa a seguir contm erros sintticos e resulta em mensagens de adver-
tncia quando se tenta compil-lo com o compilador GCC ou no ambiente
CodeBlocks usando a opo -Wall:
#include <stdio.h>
#include "leitura.h"
int main(void)
{
int x, y, z; /* Declarao das variveis */
/* inteiras x, y e z */
x = 10; /* Atribui 10 varivel x */
Y = 0; /* Atribui 0 varivel y */
z = LeInteiro(); /* L um valor para a varivel z */
PRINTF("%d", y); /* Escreve o valor da varivel y */
return 0
}
Sua tarefa consistir do seguinte:
(a) Usando o ambiente CodeBlocks, edite o programa acima exatamente
como ele apresentado aqui e salve o arquivo.
(b) Compile o programa conforme descrito na Seo 1.7.4. Voc dever
obter como resultado no painel inferior do CodeBlocks trs mensagens
de erro e trs mensagens de advertncia.
(c) Descreva o signifcado e a causa de cada mensagem de erro e de advertncia.
(d) Para cada mensagem de erro, descreva uma forma de contornar o res-
pectivo problema.
Respostas para Exerccios de Reviso | 177
(e) Para cada mensagem de advertncia, descreva uma forma de evitar que
o compilador continue a emitir a referida advertncia.
(f ) Implemente no programa as alteraes sugeridas em (iv) e (v) e certif-
que-se de que o programa obtido realmente compilado sem nenhuma
mensagem de erro ou advertncia.
3.22 Respostas para Exerccios de Reviso
1. (a) O que padronizao de uma linguagem? (b) Principalmente, por razes de
portabilidade.
2. (a) o padro da linguagem C defnido por um comit ISO. (b) C11?
3. Signifca que ela no especifcado por nenhum padro aceito de C e, portanto,
no portvel.
4. Dennis Ritch.
5. Veja a Seo 3.2.1.
6. (a) So identifcadores que possuem signifcado especial numa linguagem de pro-
gramao (b) No.
7. (a) So dentifcadores usados pela biblioteca padro de C. (b) Pode, mas no deve.
8. No, porque palavras-chave e palavras reservadas usam letras minsculas.
9. int, double e void so palavras-chave; $a e a$ usam $, que no um caractere per-
mitido em identifcadores de C.
10. Em linhas gerais, qual o contedo do conjunto bsico de caracteres da linguagem C?
11. (a) um mapeamento entre caracteres e nmeros inteiros que os representam. (b)
ASCII, EBCDIC e ISO 8859-1.
12. Por meio dos nmeros inteiros que os representam num dado cdigo de caracteres.
13. (a) 71; (b) 9; (c) 57; (d) 106 (49 + 57)
14. No. c = 'A' portvel (e legvel) c = 65 no portvel (nem legvel).
15. (a) um conjunto de valores munido de um conjunto de operaes sobre eles (b)
um tipo que faz parte de numa linguagem de programao.
16. (a) Veja Seo 3.4.1. (b) Veja Seo 3.4.2. (c) Veja Seo 3.4.3.
17. Notao convencional e notao cientfca.
18. (a) uma forma de representao para alguns caracteres especiais que no possuem
representao grfca. (b) Em que situaes sequncias de escape se fazem neces-
srias? (c) Veja Seo 3.5.3.
19. '\n' provoca quebra de linha e '\t' causa tabulao horizontal
20. (a) Um ou mais caracteres constantes entre aspas. (b) Um string constante pode
conter mais de um caractere; os delimitadores de strings e caracteres constantes
tambm so diferentes.
21. (a) Dividindo o string em substrings separados por espaos em branco.(b) Melhora
a legibilidade.
22. Sim. Existem inmeros exemplos neste livro.
23. (a) Sim. a soma do valor inteiro associado a 'A' com o valor inteiro associado
a 'B'. (b) No, pois ela depende de implementao (c) Depende do cdigo de
caracteres usado.
24. O resultado de 'Z' - 'A' depende de implementao (i.e., do cdigo de carac-
teres usado).
25. (a) 9 (b) 2 (c) dgito.
178 | Captulo 3 Introduo Linguagem C
26. (a) Constante inteira em base decimal; (b) Constante real em notao conencio-
nal; (c) Constante real em notao cientfca; (d) Caractere constante representado
como sequencia de escape; (e) String constante.
27. (a) Os operadores unrios. (b) O operador de atribuo.
28. (a) a alterao de valor produzida pelo operador em um de seus operandos. (b)
Atribuo, incremento e decremento.
29. Os operadores representados por && e ||.
30. No.
31. Por que a expresso direita da atribuio pode produzir dois valores vlidos, de-
pendendo da ordem com que os operandos da multiplicao so avaliados.
32. Operadores aritmticos, relacionais e lgicos, nessa ordem da maior para a menor
precedncia.
33. (a) Um operador representa uma operao elementar de uma linguagem de pro-
gramao. (b) um valor sobre o qual atua um operador. (c) uma combinao
legal de operadores e operandos.
34. (a) -6; (b) -2; (c) 6; (d) -2; (e) -6; (f ) 2. (De acordo com os padres C99 e C11.)
35. (a) um operador utilizado para efetuar comparaes. (b) Veja Seo 3.7.2.
36. Alguns usam smbolos diferentes; os tipos de operandos so diferentes; os resulta-
dos so diferentes; os operadores relacional da pseudolinguagem fazem parte de um
mesmo grupo de precedncia, o que no ocorre com os operadores relacionais de C.
37. Em C, 0 ou 1. Em linguagem algortmica, verdadeiro ou falso.
38. No (v. Seo 3.7.2).
39. (a) 10.5; (b) 2.5; (c) 6.75.
40. (a) a = ((b*c) == 2); (b) a = (b && (x != y)); (c) a = (b = (c + a)).
41. (a) O que um operador lgico? (b) Negao (!), conjuno (&&) e disjuno
(||). (c) 0 ou 1.
42. uma tabela que apresenta os possveis resultados de um operador lgico em fun-
o dos possveis valores de seus operandos.
43. (a) Praticamente, nenhuma. (b) Operandos, resultado e curto-circuito.
44. (a) o fato de um operador nem sempre avaliar todos os seus operandos. (b)
Conjuno (&&) e disjuno (||).
45. No. Na expresso (2) o valor de y sempre incrementado, o que no ocorre sem-
pre no caso da expresso (1).
46. Se o valor de x for 0, a avaliao da expresso (1) causa o aborto devido a tentativa
de clculo de resto de diviso por 0. Na expresso (2), o curto circuito do operador
de conjuno impede que a expresso y%x seja avaliada quando x 0.
47. (a) Porque o valor resultante da avaliao de 1/3 0? (b) Zero.
48. (a) x > 2 && x < 10; (b) x%2 == 0 || x%3 == 0; (c) x%2 == 0 && x != 6;
(d) x == 2 || x == 3 || x == 5;
49. (a) Sim. (b) Zero.
50. O valor da expresso 2/3 0. Portanto, a varivel produto recebe esse valor con-
vertido em double.
51. Uma defnio de varivel especifca o nome e o tipo de uma varivel.
52. Uma defnio de varivel informa o compilador como ele deve interpretar o con-
tedo da varivel, a quantidade de espao que deve ser alocada e o identifcador
associado a um espao em memria.
Respostas para Exerccios de Reviso | 179
53. Qual a utilidade de uma defnio de varivel?
54. Para facilitar rpida identifcao visual.
55. O smbolo = representa operador de atribuio; O smbolo == representa opera-
dor de igualdade.
56. 1.
57. (a) i recebe 2; d recebe 2.0. (a) i recebe 2; d recebe 2.5.
58. (a) uma converso de tipos efetuada automaticamente pelo compilador. (b) Para
permitir mistura de tipos numa expresso.
59. Em expresses envolvendo tipos diferentes (incluindo atribuio), em passagem
de parmetros, em retorno de funo e quando o tipo de uma varivel ou par-
metro char.
60. Consulte a Seo 3.10.1.
61. (a) No. (b) Sim. (c) Real.
62. (a) Para converter 2 em double. (b) No, pois essa converso ocorreria implicita-
mente. (c) Melhora a legibilidade.
63. (a) 2.0; (b) 2.5; (c) 2.5; (d) 2.0.
64. (a) Acrscimo de 1 a uma varivel. (b) Decrscimo de 1 de uma varivel. (c) So
os operadores represntados por ++ e --.
65. Se x uma varivel, o resultado de ++x x + 1 e o resultado de x++ x.
66. (a) 2 (b) 1 ou 2.
67. (a) 1 (b) 2.
68. Incremento no pode ter uma expresso como operando.
69. Se a varivel j for avaliada primeiro, a expresso j * j++ ser igual a 4 * 4, que
igual a 16. Se a expresso j++ for avaliada primeiro, a expresso j * j++ ser
igual a 5 * 4, que igual a 20.
70. No. Essa expresso possui todos os ingredientes para no ser portvel (v. Seo 3.9).
71. (a) Por meio de delimitadores de comentrios. (b) Como se fossem espaos em
branco.
72. Para facilitar seu entendimento assim como prover outras informaes teis sobre ele.
73. Por que um programa sem comentrios compromete seu entendimento?
74. Quando se est construindo o programa para evitar esquecimento.
75. Comentrios encontrados em livros de ensino de programao so didticos.
76. Porque comentrios desviam a ateno de quem l o programa.
77. Consulte a Seo 3.12.
78. Uma biblioteca uma coleo de componentes prontos para uso em programas.
79. Sim. Mas, uma linguagem de programao que no possui biblioteca severamente
limitada do ponto de vista pragmtico.
80. Usando os componentes prontos providos por uma biblioteca, o programador no
precisa program-los.
81. (a) a biblioteca que deve acompanhar qualquer compilador que segue o padro
de C? (b) Nenhum componente de biblioteca tm signifcado especial para um
compilador de C. Portanto, no fazem parte da linguagem.
82. Porque, apesar de acompanhar obrigatoriamente qualquer compilador padro, seus
componentes no fazem parte da linguagem em si (v. questo anterior).
83. um arquivo que contm informaes sobre os componentes de uma biblioteca
ou mdulo de biblioteca.
84. (a) Para incluir arquivos de cabealhos em programas. (b) O contedo do arquivo
cujo nome acompanha a diretiva inserido a partir da linha na qual se encontra
a diretiva.
85. (a) Quando se desejam processar entrada e sada usando a biblioteca padro. (b)
Quando se desejam incluir num programa operaes matemticas sobre nmeros
reais que no so contempladas por operadores de C. (c) Para processar strings. (d)
Para leitura robusta de dados via teclado sem uso da biblioteca padro.
86. Porque a incluso do cabealho stdio.h da biblioteca padro de C escrita como:
#include <stdio.h>
enquanto que a incluso do cabealho leitura.h da biblioteca LeituraFacil
escrita como:
#include "leitura.h"
87. Interao refere-se comunicao entre programa e usurio. A palavra iterao
refere-se a repetio e mais usada no contexto de estruturas de controle.
88. (a) um programa que dialoga com o usurio. (b) Editor de texto, navegador de
itnernet, IDE. (c) Controlador de dispositivo e virus de computador.
89. um programa robusto resistente a qualquer tipo de entrada de dados.
90. Consulte a Seo 3.14.1.
91. uma sequncia de caracteres que comea com % e especifca como um valor
deve ser escrito.
92. (a) um string que contm especifcadores de formato. (b) Quaisquer caracteres.
93. Cada especifcador de formato deve corresponder um valor a ser escrito por printf()?
94. (a) Usando o especifcador de formato %c. (b) Usando o especifcador de forma-
to %d.
95. (a) Um valor do tipo double com seis casas decimais. (b) Um valor do tipo double
com duas casas decimais. (c) Um valor do tipo int. (d) Um valor do tipo int. (e)
Um valor do tipo int. (f ) Um caractere. (f ) Um string.
(b) %5.2f
(c) %5d
(d) %-5d
96. (a) Incluindo \n num string de formatao. (b) Incluindo \t num string de
formatao.
97. Seis.
98. (a) 2.456900. (b) Um valor sem sentido. (c) 2.46. (d) 2.46.
99. 4321.
100. Porque faltou incluir a varivel resultado como parmetro de printf().
101. i = 8, j = 1
102. 1/3 = 0.000000
103. Consulte a Seo 3.14.3.
104. (a) Usurio comum no sabe o que string. (b) Nem ^C.
105. Porque o usurio pode ser induzido a introduzir dados incorretos.
106. Porque ele usa um especifcador de formato indevido (o correto seria %f, e no %d).
107. (a) um identifcador que representa um valor constante. (b) Unsando #defne,
o nome da constante e seu valor.
108. (a) Porque uma defnio de constante simblica uma diretiva e diretivas ter-
minam com quebra de linha, e no com ponto e vrgula? (b) Porque ele no se
Respostas para Exerccios de Reviso | 181
manifesta no local em que a constante defnida. (c) Como o uso de convenes
diferentes para escrita de identifcadores que pertencem a categorias diferentes
facilita a deteco desse tipo de erro?
109. Legibilidade, manutenibilidade e portabilidade so favorecidas com o uso de
constantes simblicas.
110. Usando constante, =, o nome da constante e seu valor.
111. Consulte a Seo 3.16.
112. No. Apenas programas executados sob superviso de um hospedeiro devem in-
cluir uma funo main().
113. (a) Na prtica, so aqueles sujeitos superviso e ao suporte de um sistema ope-
racional. (b) So aqueles que no possuem hospedeiro.
114. um programa executado numa interface baseada apenas em texto.
115. Consulte a Seo 3.17.1.
116. (a) primeirra funo a ser executada num programa com hospedeiro. (b) Porque
o hospedeiro a executa logo aps o programa ter sido carregado em memria. (c)
Sim, dependendo do sistema usado como hospedeiro.
117. Signifca que um programa foi executado sem anormalidades.
118. legal, mas intil (v. Captulo 4).
119. (a) Ponto e vrgula. (b) No (v. Seo 4.2).
120. Resumidamente, teste procura defeitos num programa e depurao os corrige?
121. Mensagem de erro indica que um programa no ser compilado e mensagem de
advertncia indica que um programa poder apresentar problemas quando for
executado.
122. (a) um erro que trangride as regras de uma linguagem de compilao. (b)
um errro que causa aborto de programa. (c) um errro que causa o mau fun-
cionamento de um programa, mas no provoca aborto. (d) Erro de compilao.
(e) Erro lgico.
123. Consulte a Seo 3.18.2.
124. Tentativa de diviso inteira por zero e corrupo de memria.
125. Porque ela pode antecipar a ocorrncia de um erro de execuo ou erro lgico.
126. Poder ocorrer um erro de execuo se o valor introduzido pelo usurio for igual a 0.