Você está na página 1de 82

c    

   
   


      

 
  
A Linguagem C é uma linguagem de programação que tem sua origem em
outras duas linguagens anteriores: a Linguagem BCPL e a Linguagem B. A Linguagem
BCPL foi desenvolvida por Martin Richards. Esta linguagem influenciou a linguagem
inventada por Ken Thompson, chamado B. Logo em seguida, Dennis Ritchie
desenvolveu a Linguagem C que foi implementada em um DEC PDP-11, usando o
sistema operacional UNIX.

A Linguagem C, dada a sua simplicidade e flexibilidade, tornou-se ao longo do


tempo uma das linguagens de programação mais usadas, sendo utilizada na criação e
desenvolvimento de softwares e sistemas operacionais que se tornaram famosos em
todo mundo, como por exemplo o Sistema Operacional Windows. Entretanto, a
Linguagem C atinge seus limites a partir do ponto em que os programas escritos na
linguagem atingem um certo tamanho, entre 25.000 e 100.000 linhas, devido à
problemas de gerenciamento do código. Para resolver este problema, em 1980, enquanto
trabalhava nos laboratórios da Bell, em Murray Bill, New Jersey, Bjarne Stroustrup
acrescentou várias extensões à linguagem C e chamou inicialmente esta nova linguagem
de ³C com classes´.

Em 1983, o nome adotado para esta nova linguagem foi C++. Muitas
modificações foram feitas na Linguagem C++ para que ela pudesse suportar a
programação orientada a objetos (POO).

 
  



Compiladores e Interpretadores são simplesmente programas sofisticados que
agem sobre o código-fonte do seu programa, ou seja, depois que o código-fonte de um
determinado programa é escrito ele é submetido à um Compilador ou um Interpretador
que fará com que seja possível sua execução em uma determinada máquina.

O  
 lê o programa inteiro e converte-o em um código executável.
Uma vez o programa compilado, uma linha de código-fonte está significativamente
distante do código executável. O compilador não é necessário para executar o programa,
desde que ele já esteja compilado, ou seja, neste caso não será necessário que se tenha
um programa instalado na máquina que reconheça o código em questão.

O  


lê o código-fonte do seu programa uma linha por vez e executa
uma instrução específica contida naquela linha. O interpretador deverá estar presente
toda vez que o programa estiver sendo executado, ou seja, é necessário que um
interpretador específico da linguagem utilizada esteja instalado na máquina.
Existem dois termos freqüentes:     e      . O
termo tempo de compilação refere-se aos eventos que acontecem durante o processo de
compilação e tempo de execução, aos eventos que ocorrem enquanto o programa está
sendo executado. Infelizmente, constantemente esses termos estão relacionados a
mensagens de erros, como em

           e

        
 .

 

    
 !
" entre máquinas e sistemas operacionais, ou seja, um
código escrito em linguagem C poderá ser executado em diferentes máquinas
independentemente da sua configuração física (hardware) e do sistema operacional
residente.
A linguagem C é 

, com isso desencoraja a utilização dos
goto's ± desvios incondicionais -, que geram os chamados códigos "macarronada". O
"goto" é substituído por diversos tipos de laços e desvios, tais como: while, do-
while, for; if-then-else, switch, que permitem ao programador exercer um controle
lógico mais eficaz sobre os códigos fontes de seus programas.
A linguagem C/C++ possui "#
    $
$    , isto é,
funções cujas variáveis são visíveis apenas dentro desta função e somente no
momento em que estas funções estejam sendo usadas. Assim as variáveis com
mesmo nome, que pertençam a funções distintas, são protegidas dos efeitos
colaterais (proteção de variáveis), isto é, uma modificação em nível funcional não
acarretará mudança na variável em nível global. Desta forma, mudanças de valores
de variáveis no corpo do programa principal não afetam as variáveis de funções e
vice-versa, a não ser que o programador assim o queira.
     
 , quando comparado ao código de outras
linguagem de complexidade análoga.Y
A linguagem C é  #% $ .Y  importante saber que as letras
maiúsculas e minúsculas são tratadas como caracteres distintos. Por exemplo, em
algumas linguagens, os nomes de variáveis , Y e  Y são três
maneiras de se especificar a mesma variável. Entretanto na linguagem C, serão três
variáveis diferentes. Então, quando você digitar programas em C seja cuidadoso na
utilização correta das letras.

& ' ( 
  
Atualmente, nos Estados Unidos, C é a linguagem mais utilizada pelos
programadores, por permitir, dadas suas características, a escrita de programas típicos
do Assembler, BASIC, COBOL e Clipper, sempre com maior eficiência e portabilidade,
como podemos constatar pelos exemplos abaixo relacionados:
Sistema Operacional: UNIX (Sistema Operacional executável em micro
computadores e em mainframes).
Montadores: Clipper (O utilitário de banco de dados mais usado no Brasil).
Planilhas: 1,2,3 e Excel (A planilha eletrônica com maior volume de vendas
mundial).
Banco de Dados: dBase III, IV e Access (o gerenciador de base de dados mais
utilizado no mundo).
InfoStar: O Editor de Texto mais utilizado nos USA no Sistema Operacional UNIX.
Utilitários: FormTool (Editor de formulário mais vendido no mundo).
Aplicações Gráficas: Efeitos Especiais de filmes com Star Trek e Star War.
Linguagens como o Power Builder e o Visual Basic, respectivamente as linguagens
mais utilizadas nos EUA e no Brasil.
No Brasil utilizada por empresas especializadas na elaboração de vinhetas e
outros efeitos especiais.

)   


*+
   
Deve-se entender 
Y   como sendo a capacidade da linguagem em
compreender instruções escritas em ³dialetos´ próximos do inglês (Ada e Pascal, por
exemplo) e 
Y para aquelas linguagens que se aproximam do Assembly, que é
a linguagem própria da máquina, compostas por instruções binárias e outras
incompreensíveis para o ser humano não treinado para este propósito. Infelizmente,
quanto mais clara uma linguagem for para o humano (simplicidade >) mais obscura o
será para a máquina (velocidade <).
A Linguagem C é freqüentemente referenciada como uma linguagem de nível
médio, posicionando-se entre o Assembly (baixo nível) e o Pascal (alto nível). Uma
das razões da invenção da linguagem C foi dar ao programador uma linguagem de
alto nível que poderia ser utilizada como uma subst ituta para a linguagem Assembly.
Entretanto, ainda que a linguagem C possua estruturas de controle de alto nível,
como é encontrado na Pascal, ela também permite que o programador manipule bits,
bytes e endereços de uma maneira mais proximamente ligada à máquina, ao
contrário da abstração apresentadas por outras linguagens de alto nível. Por esse
motivo, a linguagem C tem sido ocasionalmente chamada de ³código Assembly de
alto nível´. Por sua natureza dupla, a linguagem C permite que sejam criado
programas rápidos e eficientes sem a necessidade de se recorrer a linguagem
Assembly.
A filosofia que existe por trás da linguagem C é que o programador sabe
realmente o que está fazendo. Por esse motivo, a linguagem C quase nunca ³coloca-se
no caminho´ do programador, deixando-o livre para usar (ou abusar) dela de qualquer
forma que queira. O motivo para essa ³liberdade na programação´ é permitir ao
compilador C criar códigos muito rápidos e eficientes, já que ele deixa a
responsabilidade da verificação de erros para você.
Observemos o esquema a seguir:
Nível Baixo Nível Médio Nível Alto
VELOCIDADE CLAREZA
Assembler Macro C Fortran Basic Pascal Ada
Assembler COBOL MODULA-2
Forth
Antes da linguagem C tornar-se um padrão de fato (meados de 1.988, nos USA),
tínhamos, aproximadamente, o seguinte perfil de mercado:
- Aplicações de Banco de Dados
- Mainframe: COBOL e gerenciadores
- Micros: dBase, Clipper e BASIC e gerenciadores como Btrieve.
- Aplicações Gráficas: Pascal.
- Aplicações Científicas: FORTRAN e Pascal.
- Utilitários, Sistemas Operacionais e Compiladores: Assembler.
A chegada de poderosos compiladores C (Borland, Microsoft e Zortech-
Symantec), revolucionou totalmente estes conceitos pois passou a permitir a construção
de praticamente qualquer tipo de aplicação na Linguagem C, normalmente mais rápidas
do que na linguagem original e portável entre os diversos ambientes (³roda´ em DOS,
UNIX, etc. com poucas mudanças).
Devemos entender no entanto, que apenas temos uma „  „ 

,
pois a verdadeira portabilidade depende necessariamente da implementação do sistema
operacional, necessariamente aberto, o que não existe fora do mundo Unix.
Quadro de características de linguagens:
  ,  "
 % 
 ++ 


     ! 
( $  
  ótimo fraco péssimo fraco ótimo
( $  -   ótimo bom razoável fraco bom
!
$   péssimo bom ótimo ótimo bom
c     ótimo razoável péssimo fraco ótimo
O quadro anterior, deixa claro o porquê da revolução causada pela Linguagem
C, dados os inúmeros pontos fortes da linguagem e a inexistência de pontos fracos da
mesma. Não deve-se concluir apressadamente que poderemos desenvolver tudo em C e
abandonarmos todas as outras linguagens, pelos seguintes motivos:
- Alta base de programas escritos em Assembler, COBOL, BASIC, Pascal.
- Conhecimento amplo de linguagens concorrentes como COBOL, Clipper e BASIC.
- Melhor adaptação de alguma linguagem para tarefa específica como Gráficos
(Pascal), Inteligência Artificial (Prolog, LISP), matemáticas (Pascal e FORTRAN),
aplicações comerciais (COBOL, Clipper e BASIC).
As versões atuais das linguagens BASIC, C, Clipper, Pascal e COBOL, estão
muito mais semelhantes do que o eram ao tempo em que este quadro foi elaborado,
portanto na prática muitas vezes este quadro, meramente teórico, pode tornar-se
inaplicável.
À médio prazo, pode-se afirmar que a linguagem C deverá ir desalojando as
outras linguagens podendo até mesmo tornar-se um padrão de direito, porém devemos
lembrar que algumas linguagens foram propostas para isto (Algol, PL/1) e não só não
conseguiram atingir seus objetivos como praticamente desapareceram.
.( 

 !

   
Um programa em Linguagem C é formado por uma ou mais funções. Cada
função possui um nome exclusivo e corresponde à um bloco de código, delimitado por
um par de chaves {}, contendo um conjunto de declarações, expressões, comandos de
controle e chamadas à outras funções. Uma função denominada
é obrigatória em
todos os programas, pois é o seu ponto de entrada, isto é, o programa começa a ser
executado no início da função
 e termina ao final desta função. Normalmente a
declaração desta função possui a seguinte forma: Y
 ¢ mas adiante será
estudada outra forma de declaração para esta função. Ao concluir a função
¢com o
comando „ „, a execução do programa é finalizada, sendo que pelo padrão ANSI,
esta função deve retornar 0 (zero) se o programa foi finalizado com sucesso, ou um
valor maior que zero caso ele tenha sido finalizado por uma situação anormal. Além da
função
, o programa pode possuir outras funções, sendo que estas devem ser, direta
ou indiretamente, chamadas pela função
O
Abaixo, um programa escrito em linguagem C, muito simples que você pode
rodar no seu compilador:
/* Seu primeiro programa em linguagem C*/
#include <stdio.h>
void main ()
{
printf ("Bem vindo ao mundo da programação em C!!! \n");
getchar(); /* Aguarda pressionar Enter */
}

. 
 
Os comentários servem principalmente para documentação do programa e são
ignorados pelo compilador, portanto não irão afetar o programa executável gerado. Os
comentário iniciam com o símbolo ,/ e se estendem até aparecer o símbolo /,. Um
comentário pode aparecer em qualquer lugar no programa onde possa aparecer um
espaço em branco e pode se estender por mais de uma linha.

.0
$1  
Toda a diretiva, em C, começa com o símbolo 1no início da linha. A diretiva
8  inclui o conteúdo de um outro arquivo dentro do programa atual, ou seja, a
linha que contêm a diretiva é substituída pelo conteúdo do arquivo especificado.
Sintaxe:
#include < ÷  
>
ou
#include ³ ÷  


O primeiro caso é o mais utilizado. Ele serve para incluir alguns arquivos que
contêm declaração das funções da biblioteca padrão, entre outras coisas. Estes arquivos,
normalmente, possuem a extensão .h e se encontram em algum diretório pré-definido
pelo compilador. Sempre que o programa utilizar alguma função da biblioteca-padrão
deve ser incluído o arquivo correspondente. A tabela a seguir apresenta alguns dos
principais .h da linguagem C:Y Y
2 - Funções de entrada e saída (I/O)

 2 - Funções de tratamento de strings
22 - Funções matemáticas
3 2 - Funções de teste e tratamento de caracteres
"2 - Funções de uso genérico
A segunda forma, onde o nome do arquivo aparece entre aspas duplas, serve
normalmente para incluir algum arquivo que tenha sido criado pelo próprio
programador ou por terceiros e que se encontre no diretório atual, ou seja, no mesmo
diretório do programa que está sendo compilado.

. 4 ! # #5



 Você pode não ter percebido, mas no código em C apresentado no item 1.6
usamos duas vezes o ponto-e-vírgula, quando terminamos a declaração dos comandos
printf() e getchar(). Ele é usado para separar diferentes comandos dentro do seu código
em C. Durante o processo de compilação executado pelo compilador, o ponto-e-vírgula
mostra ao compilador quando uma linha de comando termina e quando outra linha de
comando se inicia. Ou seja, se você esquecer do ponto-e-vírgula seu compilador irá
acusar um erro pois ele não irá saber quando termina ou começa um determinado
comando dentro do código que você digitou.

6
  7   
8$
 Ao criar um programa em linguagem C, você coloca seus comando em um
arquivo-fonte, que tem a extensão O . Se o seu programa for compilado com sucesso, o
compilador irá criar um programa executável com a extensão O  . Durante a
compilação, o compilador cria em seu diretório outros arquivos com extensão O .
Estes arquivos contém as instruções em forma binária, ou seja 1s e 0s, que o
computador compreende.

9%  c 


 apresentado à seguir, uma síntese do que foi tratado em cada item deste
módulo. Com esta síntese você poderá relembrar conceitos vistos durante nosso estudo
ou mesmo direcionar seu estudo, caso você já tenha conhecimentos na Linguagem C.
:Y :    
     :apresenta um breve relato sobre o
desenvolvimento da Linguagem de Programação C. Nele é mostrado que a Linguagem
C foi desenvolvida por Dennis Ritchie e que ela é na verdade uma linguagem derivada
de outras duas linguagens de programação anteriores, a BCPL e a Linguagem B.
Mesmo sendo uma linguagem flexível e poderosa, a Linguagem C chegou a seus
limites, e com isso, o desenvolvimento de uma nova linguagem tornou-se inevitável,
sendo desenvolvida a Linguagem C++, que na verdade era a Linguagem C com novas
características que superaram seus limites. Foram feitas várias modificações e melhorias
na Linguagem C++ para que ela pudesse suportar a programação orientada a objeto
(POO).
:Y :    
   


: neste item, foi mostrada a
diferença entre compilador e interpretador. Compiladores e Interpretadores são
programas que ³traduzem´ um código-fonte de um programa para a linguagem que a
máquina entende. No caso do Interpretador, ele faz isso linha por linha do código-fonte,
toda vez que o programa em questão é executado. Ou seja, é necessário que exista na
máquina um interpretador específico instalado para a linguagem de programação em
que o programa em questão foi escrito. No caso do Compilador é gerado um programa
executável, ou seja, o Compilador cria um arquivo que pode ser lido pelo sistema
operacional da máquina, eliminando assim a necessidade de um interpretador instalado.
Foi visto também que o termo tempo de compilação refere-se aos eventos que
acontecem durante o processo de compilação e tempo de execução, aos eventos que
ocorrem enquanto o programa está sendo executado.
:Y :  

     : neste item, apresentou-se as
principais características da Linguagem C, entre elas: que a Linguagem C é portável; a
Linguagem C é estruturada; a linguagem C/C++ possui sub-rotinas com variáveis
locais; seu código é compacto e rápido; a linguagem é case-sensitive.
:Y : &   '  ( 
   :devido à sua compatibilidade com
outras linguagens de programação, como por exemplo, Assembly, Cobol, Clipper,
Basic, a Linguagem C é largamente utilizada no desenvolvimento de programas,
sistemas operacionais e até em efeitos especiais em filmes.
:Y : )   
*+
   :neste item
foi feita uma comparação entre a Linguagem C e outras linguagens de programação.
Mostrou-se que a Linguagem C se classifica como uma linguagem de nível médio, pois
mesmo possuindo estruturas de controle de alto nível, ela permite a manipulação de bits,
bytes e endereços de uma maneira bem próxima à máquina. Além do mais, a
Linguagem C é veloz e tem uma alta portabilidade. Mas mostra-se que não é possível
pensar em abandonar as outras linguagens e usar-se somente a Linguagem C.
:Y : .  ( 

    !

     : foi estudado
neste item que um programa em Linguagem C é formado por uma ou mais funções.
Cada função possui um nome exclusivo e corresponde à um bloco de código, delimitado
por um par de chaves {}, contendo um conjunto de declarações, expressões, comandos
de controle e chamadas à outras funções. Uma função denominada   é obrigatória
em todos os programas, pois é o seu ponto de entrada, isto é, o programa começa a ser
executado no início da função  e termina ao final desta função.
:Y : .   
 : comentários servem principalmente para
documentação do programa e são ignorados pelo compilador, portanto não irão afetar o
programa executável gerado. Os comentário iniciam com o símbolo ,/e se estendem até
aparecer o símbolo /,.
:Y : .  0
$ 1  : neste subitem foi estudada a diretiva
#include inclui o conteúdo de um outro arquivo dentro do programa atual, ou seja, a
linha que contêm a diretiva é substituída pelo conteúdo do arquivo especificado. Ela
serve para incluir alguns arquivos que contêm declaração das funções da biblioteca
padrão, entre outras coisas.
:Y : .   4    # #$
: foi visto que o ponto-e-vírgula é
usado para separar diferentes comandos dentro do seu código em C. Durante o processo
de compilação executado pelo compilador, o ponto-e-vírgula mostra ao compilador
quando uma linha de comando termina e quando outra linha de comando se inicia.
:Y : 6  
    7     
8$: foi explicado
detalhadamente os tipos de arquivos usados na programação em Linguagem C, como
por exemplo, os arquivos com extensão ,   e ";.
Y
c 

   0 < ' =
 
  
Y

È  
     
Na Linguagem C existem palavras que são de uso reservado, ou seja, não pode-
se usá-las para escrever programas, por exemplo usando o nome de uma palavra
reservada para referenciar uma variável. Uma palavra reservada é essencialmente um
comando e, na maioria das vezes, as palavras reservadas de uma linguagem definem o
que pode ser feito e como pode ser feito.
O conjunto de palavras reservadas em Linguagem C especificado pelo padrão
ANSI C são as relacionadas abaixo:
 Y  Y Y 
Y


 Y  Y  Y  Y

 Y  Y
  
Y Y


Y 
Y

Y Y

 Y Y 
Y   Y

 Y 
Y  Y Y

 Y Y Y Y

Y Y  Y Y

Como já foi dito no Módulo 1, a Linguagem C diferencia letras maiúsculas e


minúsculas, ou seja, „ é uma palavra reservada da Linguagem C mas  ou
„ não é. Reforçando o que já foi mencionado, as palavras reservadas só irão
executar os comandos que lhes foram designados.

>   <


4     
VY  YY YY YY Y
Y

 
Y
 Y  Y
  YY

 Y  
 Y   Y  Y Y 
Y Y O OO  !Y " Y  Y  Y  Y
 
 Y  Y Y  
#Y Y 
 Y $ Y  

Y  Y   Y


 %
:Y :YY  Y Y 
 Y Y Y Y 
Y &'V'!!'('Y ''!!'')Y  Y Y 

Y
&'*')+Y
:Y :YY YY 
Y   Y,  Y
 YY 

 +Y
:Y :YY
YY YY'*'YY

Y 
 
YY 
YY Y
Y Y Y
YY 
 YYY YY  +Y
:Y :YY 
YY 

$ Y Y
Y Y 
Y Y Y
!Y-#Y Y
Y Y Y 
Y  Y  Y 
Y  Y 

Y 
Y  $ Y 
Y  Y

 !Y
Aqui estão alguns exemplos de nomes de identificadores corretos e
incorretos:



  


count 1count
test23 Olá! Aqui
high_balance high..balance
ïYY Y

 Y./Y 
 
 YY YYY 
Y #Y    !Y
0 Y 
Y
Y Y  Y
 Y Y Y./Y

 Y 
 
 YY  Y
Y
Y Y ..1Y Y #Y  
 Y   !Y Y  2Y Y 

Y Y Y 
 Y
3  YY3  Y #Y
 Y Y
 YY  Y  Y Y 
 !Y4
Y
 Y
Y 
Y  #Y
2 Y 
 Y  !Y

Um identificador não pode ser o mesmo que uma palavra reservada e não devem
ter o mesmo nome de uma função ± tanto uma função que você tenha escrito como uma
função de biblioteca da linguagem C.

È     
Quando um programa é escrito em qualquer linguagem de programação é
necessário a definição de algumas variáveis. Variáveis são instâncias em que serão
armazenados valores utilizados durante a execução de programas. Estas variáveis
podem ser modificadas para suportar diferentes tipos de dados. Na tabela abaixo
constam os tipos básicos de dados da Linguagem C:
7  7 2? " @  
$
Char 8 -128 a 127
Int 16 -32768 a 32767
Float 32 3,4E-38 a 3,4E+38
double 64 1,7E-308 a 1,7E+308
void 0 sem valor

È       


4 Y Y Y   YY Y$ YY
$ Y
Y
Y
Y
 Y    Y Y Y  #!Y Y  #Y Y Y Y  Y  Y  
 Y  Y    Y
Y 
Y  
 Y 
 $ !Y Y 5 2Y Y 
Y Y  
 Y O Y

 O YYY !' Y 


 Y O Y
 O YY Y 
Y  Y
 Y  Y Y  Y 
 
Y Y 
!Y ï
YY Y Y 
Y  Y Y Y

!Y VY Y Y  
Y  
Y  Y  Y  Y 
 Y  Y  Y   Y Y  Y
 
 YY!Y
7  7 2? " @  
$
char 8 -128 a 127
unsigned char 8 0 a 255
signed char 8 -128 a 127
int 16 -32768 a 32767
unsigned int 16 0 a 65535
signed int 16 -32768 a 32767
short int 16 -32768 a 32767
unsigned short int 16 0 a 65535
signed short int 16 -32768 a 32767
long int 32 -2147483648 a 2147483647
signed long int 32 -2147483648 a 2147483647
unsigned long int 32 0 a 4294967295
float 32 3,4E-38 a 3,4E+38
double 64 1,7E-308 a 1,7E+308
long double 80 3,4E-4932 a 1,1E+4932
VY  YY
Y Y#Y  Y
Y 
#YY
Y
 O Y
 Y!Y5 2YY  Y 
YY
Y
 O Y  Y YYO!Y'YO
 Y, !Y4
Y%Y

unsigned x;

unsigned int x; Y

declaram igualmente variáveis inteiras sem sinal.



 Y Y Y  Y 
Y  Y 
Y 

Y 
 Y  
 Y  Y #Y
 Y Y  Y Y 
 
 Y V 00!Y 6Y 
Y Y 
Y Y Y
Y Y7 8Y
Y Y
YY9:/;YY:/<YYY 
YY Y
Y YY
 #Y#Y
 
Y3
 Y
 !

È       



 Y #Y  =  Y Y Y 

Y Y  #Y  Y  Y  Y  Y  #Y
Y
   Y
Y Y #!YV Y
 YY 
Y 
 Y Y  YY

Y  Y Y Y Y   Y  Y  Y 
Y  !Y V Y 
 Y #Y    Y Y

 Y  YY  !YY

 YO  #Y  Y 
 Y
YY Y Y  !Y

 Y O  #Y   Y  
 Y Y , Y Y Y  Y Y  Y   Y  #Y

 
 Y  Y   Y Y  Y 
Y  
 !Y VY  
#Y Y 
 Y   Y Y

 
Y 
YY

Y
YY Y Y Y  YY
Y Y Y Y 
 
Y
Y7
Y  8Yà '+YYY#YY 
Y
Y Y 
 Y Y  !Y5 YY Y

Y Y 

Y Y
%Y

<tipo> <nome>

Exemplos:
int mul = 100;
char a, b, c;
float valor;
Y

È !    " " 


'Y  Y Y   Y Y    Y Y 

#Y Y 
 
Y Y 
Y 
Y
 YY YYY Y YY
Y

 Y
YY  YY

Y

Y Y Y
 YY
Y
 ,YY Y!Y' Y  Y Y
YYY  Y
PIY YY
Y7.:>:?@/A?.A8Y Y
Y 
YY  YYYPIY 
Y YY
 Y  
Y Y 
Y 7.:>:?@/A?.A8!Y -Y   Y Y   Y Y 
Y  Y Y
 Y
Y%Y

#define <nome_da_constante> valor

Exemplos:
#define PI 3,1415926536

#define SINAL "aberto"

#define MULT A*B

Observe que na definição de uma constante não há o ³;´ no final. Se for


colocado, este fará parte do valor associado à constante.

È !  " " # $   %" 


ïY

#Y  Y YY  Y 
Y Y  YY 
#Y YY
;Y Y:AYYYY:B!Y'Y  Y 
 Y YY;YY Y"Y Y Y,  YYBY
Y<!YïY YY3
Y:BYYY Y Y;YY !Y'Y  Y 
 YY Y:AY Y
Y& $ Y Y Y,  YYBYY@Y Y Y
 YYVYYCY Y YY:BY
::Y :/Y :.Y :>Y Y :?!Y 4
Y Y Y 3
Y  Y :BY Y :AY Y  !Y 4
Y  Y Y

D2 Y Y Y  Y Y   Y 
  Y #Y  YY  YY
Y Y Y
   Y   Y
YY Y Y YYYY Y Y


!Y6Y
 Y  Y Y 
Y Y'(8Y & Y 
Y  Y Y Y )Y  Y Y
 Y Y 
Y  !Y 6Y  Y  Y Y Y Y 
!Y V Y  #Y
  Y %Y

hex = 0xFF; /* 255 em decimal */

oct = 011; /* 9 em decimal */

È ! È " " )"  


' 
YYY  Y 
YY  YYYYY O!Y6Y 
 YY Y
 YY 
 
 Y
Y  !Y4
YY'*+  ,Y Y 
 !YY
-#Y  Y 
 Y Y 
 
!Y6Y  Y 
 
Y  Y Y
Y Y
 
 Y
YYE!Yï
Y',Y Y 
 Y Y Y Y Y
!Y

È ! -   ./  " 


 
Y  Y  Y   Y 
 
Y 
Y   Y   Y 
Y   Y

 
 Y Y  Y YY

YY 

Y #Y , YY 


Y 
 YY
Y 
 YY

YY !Y4
Y YY  YY
 Y   Y 
 
Y Y

Y
   !Yï  Y   Y #Y 
 YYYY  
% Y
`  )  Y - Y )  Y

FY G
  Y FY V#YY
 
Y

FY Nova linha F


Y G
YY 

Y

FY H #Y


Y F8Y V  Y

FEY V 
Y FBY - Y

FFY I

Y
Y FY H #Y
 Y

FY Y 


Y F-Y  Y Y

F-Y  Y Y YY YY

Usa-se um código de barra invertida exatamente da mesma maneira como usa


qualquer outro caractere. Por exemplo:

ch = µ\t¶;

printf (³este é um teste \n´);

ï Y
 YY  Y

Y
 Y Y #YYY#Y
Y7 Y
Y Y 8YYY  YY YY!Y

È 0%   
VY  YYY Y
 YY

 Y
 !Y6Y

YY Y ,Y Y
YY 
Y
Y

Y  Y  YY   Y  ,  !YVY  YY
 Y
2 Y   Y 
 YY

 %YOO YOO O YOO!Y

È 0 %   "1


O operador ³=´ atribui um valor ou resultado de uma expressão contida a sua
direita para a variável especificada a sua esquerda. Exemplos:
a = 10;

b = c * valor + getval(x);
a = b = c = 1; /*Aceita associação sucessiva de valores*/

È 0 È%   2"+" 
São aqueles que operam sobre números e expressões, resultando valores
numéricos. São eles:
'  
„Y Y

$Y 
#Y

JY   #Y

KY  #Y

LY  YY #Y&


 YY #Y
)Y

$Y Y Y&

Y 
)Y

È 0 %   
  
Operam sobre expressões, resultando valores lógicos de TRUE (verdadeiro) ou
FALSE (falso). são eles:
'  

ßY  MN -
YY
Y
Y

c 
   

YY

 3 4 
VY
Y Y

 Y
 YY #YO!Y" Y Y

 Y
$ Y

 YY Y  Y$ Y

YY 
YY 
 #YY
Y$Y
Y
 Y
 Y  Y
 !Y5 Y 
YYYY Y
Y

Y
Y Y 

Y Y !Y 4
Y 
Y Y 

Y Y  #Y  Y
  Y Y
 Y
 YY Y 
Y Y #Y
 Y
Y  YY 
Y
Y

Y
Y  YY
 
YY Y 
Y
Y 

Y Y!Y Y Y   Y
 Y Y  YY

Y
YY #YOYY

Y 
Y Y
YY

Y , Y Y 
$!Y OY Y  Y Y Y Y Y Y Y 

Y
 Y YYY YY

 !Y YY

Y
YYY  Y

 Y Y  Y  Y 
  Y 
Y 
Y 

 !Y 6Y  #Y Y Y #Y


YY  Y Y Y Y
Y  , !Y4
YYY #Y
 Y
YY #YO
Y
Y Y  %Y
void ola_mundo (void)

printf(³Olá mundo! \n´);

VY
Y YO YYY  YY YY #Y#Y

Y Y
!YïY  Y
  Y Y  Y 
#Y

Y


YY
YY Y  Y
YY #Y 
!Y
YY #Y#Y Y
Y
Y


Y Y
 Y$ Y
 
YYYY #Y
Y O !Y 'Y O Y  Y 
 Y  Y 
=
 Y Y  Y Y  #Y #Y Y 
=
 !Y 6Y

=
Y Y Y 
#Y  Y Y 

Y  Y 
Y Y  #!Y 4
Y Y  Y  Y


 Y Y OY  Y 
 Y  Y Y    Y 
Y  Y 
2  Y #Y

=
 !Y " Y Y  #Y #Y Y 
=
 Y $ Y  
Y O Y 
Y  Y

2  !Y4
Y 
Y Y #Y   $ YYYY #Y  YY
2  !Y' Y



 Y

 YY YY Y #Y Y Y YY #!Y'Y

Y
Y  
Y YY #YO %YY
#include <stdio.h>

void ola_pessoal(void)

printf("Ol pessoal!\n");

void main(void)

ola_pessoal();

}Y

Ao executar esse programa, a função


 é executada primeiro. Como se pode
ver, o único comando em
 é a chamada da função   . Quando C encontra a
chamada da função, imediatamente transfere a execução do programa para a função,
iniciando a execução do programa com o primeiro comando da função. Depois que o
último comando da função termina, a Linguagem C transfere a execução para o
comando que segue imediatamente a chamada da função.
Para compreender melhor esse processo, mude a função main dentro do
programa anterior como mostrado aqui:
void main(void)
{

printf(³Prestes à chamar a função \n´);

oi_pessoal();

printf(³Voltei da chamada da função \n´);

 È    "  3 4 


OY Y  Y  Y   Y #Y Y 
Y  Y 3 Y  Y 

 Y   Y  Y

 
Y Y Y
 Y 
Y
  Y  !Y4
Y 
Y Y
Y
YY Y
 #Y
  $ Y

Y 

YY
YY YYYO!YY

4
Y Y Y 

Y Y  
Y Y Y  #Y  Y  Y Y Y 
Y
 YY YY
Y
Y
Y Y  Y.Y %Y
#include <stdio.h>

void tres_olas(void)

int contador; /* Variavel */

for (contador = 1; contador <= 3 ; contador++)

printf("Oi pessoal! \n");

void main(void)

tres_olas();

" Y Y  
Y 
 Y 
Y Y Y  #Y  Y  Y  Y 
Y   Y

 Y #Y   Y
YY #!YY

4
Y Y Y 

Y Y Y   Y 
 Y Y Y  #Y Y Y 
Y
Y YY  YY  
YY
YY Y #Y Y !Y Y Y
 #Y
 
Y   Y
 Y Y
#Y 
Y 
 YY, YY #YY
Y Y
Y
YYO!Y
YY

  3 


" Y Y 

Y Y
Y $ Y Y Y Y  #YOY 
Y 

Y Y


Y Y YY

Y 
!Y-Y
YOYY Y #YYY Y
 Y Y 
 Y 
Y  Y  Y Y 
 Y  Y Y 
Y   Y 
Y  Y
  Y Y

Y Y Y  %Y  Y Y  Y Y Y 
Y YOY $ Y 
Y Y Y
 #!YY YY 

Y
 YYOYYY 

Y
 Y
 Y  !YHYY ,Y 
Y  
 Y Y YOYOYYYY  Y  !Y
CY Y #YY 
Y& 
)Y 
!Y4
YYY

YY  
Y Y  Y
  !Y" YY

Y YOY YY #Y  Y Y
Y YY YY
 #YO Y
2 Y Y
Y
Y   YYY Y 
Y %Y
YY
#include <stdio.h>

void ola_pessoal(void)

printf("Ola, pessoal! \n");

void tres_olas(void)

int contador;

for (contador = 1; contador <= 3; contador++)

ola_pessoal();

void main(void)

tres_olas();

}Y

YY

 / "  5 " 


6Y 
=
Y Y Y 
Y  Y Y Y  #!Y VY 
Y  Y 

 Y

  Y   Y 
=
 Y 
Y Y  #Y 
!Y OY Y  Y Y Y Y   Y 
Y

Y 
Y  
Y 
=
 Y 
Y  Y   Y Y Y Y 
$ Y  Y 3 !Y 4
Y
Y  
YY  Y  
#YY #Y  Y Y YY #YO Y

2 Y %YY

YY

void tres_olas(void)

int contador;

for (contador = 1; contador <= 3; contador++)

ola_pessoal();

}Y

Uma função mais útil permite especificar, como um parâmetro, o número de


vezes que quer que o programa exiba a mensagem. Para usar um parâmetro, a função
precisa especificar o nome e o tipo do parâmetro, como mostrado aqui:
void ola_conta(int msg_conta)

- Y  Y Y  #Y Y 


Y Y 
=
Y Y Y O Y
 !Y " Y  
Y  #Y Y YOY   
Y 
Y Y Y  #Y 
  Y
   
YY
Y YY  YY
 Y
YY
=
Y %Y

YY

ola_conta(2); /*Exibe a mensagem 2 vez es*/

ola_conta(100); /*Exibe a mensagem 100 vezes*/

ola_conta(1); /*Exibe a mensagem uma vez*/

O programa a seguir ilustra como pode usar uma função com um parâmetro:
YY

YY

YY

YY

YY

YY

YY

YY
YY

#include <stdio.h>

void oi_pessoal(void)

printf("Ola, pessoal! \n");

void ola_conta(int msg_conta)

int contador;

for (contador = 1; contador <= msg_conta; contador++)

oi_pessoal();

void main(void)

printf("Exibe a msg duas vezes\n");

ola_conta(2);

printf("Exibe a msg cinco vezes \n");

ola_conta(5);

}Y

YY

 !5 " 6" 


Em geral, pode-se passar um número irrestrito de parâmetros para uma função.
No entanto, as pesquisas mostram que, quando o número de parâmetros excede sete, a
função mostra-se mais difícil de se compreender e usar corretamente, ficando, portanto,
mais susceptível a erros. Quando a função usa mais de um parâmetro, precisa
especificar o tipo e o nome de cada parâmetro e separar os parâmetros por vírgulas,
como mostrado aqui:
YY
void uma_funcao(int idade, float sal, int num_cargo)

/*Comandos da função*/

Quando o programa chamar a função, será necessário especificar valores para


cada parâmetro, como mostrado aqui:
uma_funcao(33, 40000.00, 534);
YY

 0
"   3 
C  Y  Y  Y 
Y
Y   Y Y

Y
  !Y 4
Y

 
Y Y
 YY 
Y Y #Y
  
Y 
Y Y Y
Y Y 
Y
Y Y  %Y

return (resultado);

'YYY
Y YY #Y

Y&O¢Y Y !)Y
YYYY #!Y
4
Y Y Y Y #Y

Y Y
YYYOYY  
Y
 
YYYY
 #Y YYYYY Y 
Y %Y
YY
YY
int uma_função(int valor)

/*Comandos da função*/

A função a seguir, retorna o cubo do valor inteiro que o programa especifica


como seu parâmetro. Por exemplo, se o chamador passar o valor 5 para a função, a
função retornará o valor 5*5*5, ou 125:
int i_cubo(int valor)

return (valor *valor *valor);

Y  Y Y  #Y Y Y Y


Y 
Y


Y Y
 Y Y  Y Y

!Y 'Y  Y 
Y Y  #Y Y Y Y 
 
Y Y
 Y Y  #Y
Y&Y  Y Y
YY

)YY Y
Y YY  YY 
YY

YY

Y
YY Y

Y #YY YOY Y 
Y %
result = i_cubo(5);

printf(³O cubo de 5 é %d \n´, I_cubo(5));

'Y

YY  
Y YY #YO
Y
Y

Y
 Y
 Y
 YY
%Y
#include <stdio.h>

int i_cubo(int valor)

return(valor * valor * valor);

void main(void)

printf("O cubo de 3 Ã %d \n", i_cubo(3));

printf("O cubo de 5 Ã %d \n", i_cubo(5));

printf("O cubo de 7 Ã %d \n", i_cubo(7));

}Y

Os valores que são passados para uma função precisam corresponder aos tipos
de parâmetros contidos dentro da declaração dessa função. Por exemplo, se quiser
determinar o cubo de um valor em ponto flutuante, crie uma segunda função chamada
r , como mostrado a seguir (observe que o valor de retorno também é do tipo
float):
float f_cubo(float valor)

return (valor *valor *valor);

}Y



 7 
" 
" Y Y   Y Y  
Y Y Y
Y Y Y  #Y Y Y
Y Y  #Y Y  #Y Y

Y Y 
Y    Y 
Y Y 
!Y 'Y


Y#Y Y   
Y 
 Y  Y
YY #Y YY Y
!Y
ïYY YY  YY #YY #Y 
!Y
' 
 Y

 Y Y  Y Y 2Y3 Y  Y
Y Y Y
 Y  Y

Y Y
Y
Y Y #Y  , !Y4
YY  
YY #Y
 Y 
YY  
%Y
int compara_valores(int primeiro, int segundo)

if (primeiro == segu ndo)

return (0);

else if (primeiro > segundo)

return (1);

else if (primeiro < segundo)

return (2);

VY #Y YY Y


 Y  YYY%Y
)  
= 
BY ' Y
 Y #Y  Y

:Y 'Y

Y
YY
Y YY  Y

/Y 'Y  Y
YY
Y YY

Y

Y

Y$ Y
Y
Y Y  YY 
Y Y Y Y
!YOY
Y Y Y  Y Y

Y 
 Y Y  Y  Y
Y  Y  Y
Y

Y

Y Y  Y Y,  YY 

!Y-Y
Y Y   Y$ Y



YY #Y
Y YY Y Y Y Y
Y Y 
Y %Y
int compara_valores(int primeiro, int segundo)

int result;

if (primeiro == segundo)

return = 0;

else if (primeiro > segundo)

return = 1;

else if (primeiro < segundo)

return = 2;

return(result);
}

Neste caso, como a função é simples, pode-se ter dificuldades em compreender


qual a vantagem de usar um único comando de return. No entanto, à medida que as
funções se tornarem mais complexas, a vantagem ficará mais clara. Pode-se observar
que, algumas vezes, usar mais de um comando return produz um código mais legível do
que a alternativa de um único return. Deve-se escrever o código mais legível e
facilmente modificável quanto possível; se usar múltiplos return atingir os objetivos
pré-estabelecidos, então utilize quantos comandos return forem necessários.
Y

 8"-"  3 


VY 
Y  Y  Y 
 Y Y 
  Y  
Y  Y  Y Y

Y Y Y

=
Y Y Y  #Y  Y Y 

Y 
Y Y  #! Y  Y   Y  Y
 Y  Y 
 Y 
Y Y  Y Y  Y 

Y 

Y  Y Y 
Y Y
Y  Y 
 Y  Y Y 
Y 
Y  Y Y  

Y Y Y Y  #!Y -Y
YPYY Y Y

 Y Y Y  YY Y

Y ,Y  
Y
 Y  Y 
YY
Y 

!Y4
YY  YY
Y  
Y
 YY
 #YY  Y

Y
Y

Y Y YY
=
YYY

YY Y #!Y
4
YY  
Y Y

Y Y Y Y  YO
Y
!YV Y YY #Y
 Y YY

YYY

YY  
Y Y
Y YY  %YY
int i_cubo(int); /*Retorna um parâmetro int*/

float f_cubo(float); /* Retorna um parâmetro float*/

Como pode-se ver, o protótipo da função especifica os tipos de parâmetro e de


retorno da função. O programa a seguir usa dois protótipos de função para eliminar a
necessidade de ordem da função:
#include <stdio.h>

int i_cubo(int);

float f_cubo(float);

void main(void)

printf("O cubo de 3 Ã %d \n", i_cubo(3));

printf("O cubo de 3.7 Ã %f \n", f_cubo(3.7));

}
int i_cubo(int valor)

return(valor * valor * valor);

float f_cubo(float valor)

return(valor * valor * valor);

}Y

 9.1"  :$ 


N  Y  Y Y  #Y
Y 
Y Y 
Y 

Y Y  Y
   YY Y  Y

!YVY  YY
 
Y Y  YY YY Y


YY 
Y YY  
YY

#YY !Y4
Y YY Y 
YY
 #YY Y
Y 
Y

!Y

V YY  
Y YY 
Y Y YY 
YY  Y
Y 
 Y 
Y #Y Y Y 
Y  Y   Y  Y  Y 
Y 
 !Y N  Y

 Y

 Y  Y  Y
 Y Y YY #!YVY
Y Y

 Y
 Y  YY  YY YY #Y Y
 Y Y#Y
Y

YY
Y Y
  Y
Y  
Y
 YY Y YY

Y
Y


Y Y Y Y Y 
 Y Y 
 
 !Y V Y   Y  Y 
2 Y 
 Y  Y 
#Y   Y

Y
YY #YY YY #Y 
#Y  Y
 YY

#!Y

YY

 (3 4 ;   " / "


N  Y   Y

Y 
 Y Y YO!Y " Y Y 
Y  #Y #Y


Y Y
YYYOY&YY YYY


YY 
YY !)Y
  $
Y 

Y Y 
Y Y Y Y

Y Y  #!Y 'Y 

Y Y  
Y Y Y  #Y
 OY
Y

YY YY
2 Y 
 YYYO!YVY #Y

YY Y
Y Y
YYYY&

Y YY YY #Y   YYYY

Y
Y #)%Y
YY
#include <stdio.h>
float valor_medio(int a, int b, int c)

return ((a + b + c) / 3.0);

void main(void)

printf("A média de 100, 133 e 155 Ã %f \n",

valor_medio(100, 133, 155));

}Y



     
VY  YY
Y 

Y
 Y
YY  Y  !Yï  Y
 Y #Y
 Y Y 
 Y   Y  Y  Y  Y Y 
 Y Y 2Y   Y 
Y Y
 #Y Y YY 
#YY
!Y'Y

YY  
Y 
YY  YY Y

Y  !Y VY  #Y  O Y  
Y .Y 
 Y Y Y Y Y Y 
 Y P Y 
 Y  Y

 Y:Y/YY.Y
  !YVY #YYY

YY
YY Y
!Y-Y
Y Y Y Y Y
 Y #Y  YPY #YY 
Y 
Y

 YY Y
 Y , YYYY Y #Y !Y
#include <stdio.h>

void valores_locais(void)

int a=1, b=2, c=3;

printf("a contÃm %d b contÃm %d c contÃm %d \n", a,b,c);

void main(void)

printf("a contÃm %d b contÃm %d c contÃm %d \n", a,b,c);

}Y
YY

 È<)1  3 


" Y Y 

Y Y Y  #Y Y   Y Y 
Y Y 
Y Y


Y Y
=
 YY Y
 Y  YY!Y" YY #Y
YY  YY
 
YY YYY Y Y Y
 Y  YY
=
 YY Y YY
Y
Y

Y
Y


YY #YY

Y
YY #Y 

!Y
Embora o uso da pilha seja poderoso porque permite que o programa chame e
passe as informações para as funções, também consome tempo de processamento. Os
programadores chamam a quantidade de tempo que o computador requer para colocar e
retirar informações da pilha de sobrecarga da função. Para compreender melhor o
impacto da sobrecarga da função no desempenho do seu programa, considere o
programa a seguir. Primeiro o programa usa um laço para somar os valores de 1 a
100.000. Em seguida, repete um laço novamente, mas usa uma função para somar os
valores, como mostrado aqui:

YY

#include <stdio.h>

#include <time.h>

float soma(long int a, float b)

float result;

result = a + b;

return(result);

void main(void)

long int i;

float result = 0;

time_t hora_inicio, hora_parada;

printf("Trabalhando... \n");

time(&hora_inicio);
for (i = 1; i <= 100000L; i++)

result += i;

time(&hora_parada);

printf("Usando laço %d segundos \n", hora_parada - hora_inicio);

printf("Trabalhando... \n");

time(&hora_inicio);

for (i = 1; i <= 100000L; i++)

result = soma(i, result);

time(&hora_parada);

printf("Usando função %d segundos \n", hora_parada -

hora_inicio);

}Y

Na maioria dos sistemas, os cálculos baseados em funções podem requerer quase


o dobro do tempo de processamento. Portanto, quando usar funções dentro dos
programas, é necessário considerar os benefícios que elas oferecem versus a sobrecarga
no desempenho que introduzem.
YY

YY

      =1 


Além das variáveis locais, a Linguagem C permite que os programas usem
variáveis globais, cujos nomes, valores e existência são conhecidos em todo o
programa. Em outras palavras, todos os programas em Linguagem C podem usar
variáveis globais. O programa a seguir ilustra o uso de três variáveis globais a, b e c:
#include <stdio.h>

int a = 1, b = 2, c = 3; /* Variaveis globais */

void valores_globais(void)

printf("a contÃm %d b contÃm %d c contÃm %d \n", a, b, c);

void main(void)

valores_globais();

printf("a contÃm %d b contÃm %d c contÃm %d \n", a, b, c);

}Y

" Y Y



YY YY Y Y  YOO O YYOY
Y Y
 YY
Y !Y' 
Y Y Y
 Y  Y #Y 
 Y
YY
 Y  Y   !Y Q 
Y 
 Y  Y  Y Y  Y  Y   Y Y 

Y
Y 
Y Y 

Y  Y 
 Y Y 
Y Y  Y

 Y Y Y Y

Y !Y ï
Y  Y 
 Y  Y  Y 
 
Y  Y Y Y  

Y
 YY  
Y

 Y Y #Y,  YY

!Y
YY

 )    "  >      


=1 
Y Y

Y Y
 Y  Y  Y YYYY Y
Y YY
Y Y Y YY Y
Y Y Y  Y

Y 
Y
YY Y #!Y
4
YYY

YY  
Y Y Y
 Y  YYYY !YVY #YOY Y Y

Y Y YYY Y
 Y  YYY %Y
#include <stdio.h>
int a=1, b=2, c=3; /* Variáveis globais */

void conflito_a(void)

int a=100;

printf("a contÃm %d b contÃm %d c contÃm %d \n", a, b, c);

void main(void)

conflito_a();

printf("a contÃm %d b contÃm %d c contÃm %d \n", a, b, c);

}Y

Y " Y  Y Y 


 Y  Y Y   Y  
Y Y Y Y   Y Y

Y 
YY
Y !YY 2YY
Y Y
 Y YY #YOYY
Y
YY Y
 Y
YY #!Y

YY

 !& 
' Y 

 Y  Y 
 Y 
Y   Y Y 
=
 !Y " Y Y

=
YY YY Y #YY  YY Y Y  Y  Y Y Y

Y
Y
Y
 
YPY #Y Y Y Y
 Y Y
=
 !Y6 YY Y

Y
Y   
Y  Y YY #Y
Y Y
=
 Y Y Y
YY


Y  #!Y " Y Y  #Y 
Y Y 
Y  Y 
 Y Y  Y Y  #Y 
Y
  Y 
Y Y  #Y #Y Y  Y 
Y Y  #Y 
!Y 4
Y Y Y


YY  
Y Y
2 Y
=
 Y& Y
 YYYY )Y
YY #Y O!YVY
 #Y
Y YY 
Y Y
 Y 
Y:BBY Y
 Y Y Y 
YY
 !Y
" YY #Y

YY

Y
Y Y
 Y Y
 !YYY  YY
Y Y
Y
YY #Y#Y
Y Y
 Y Y
 Y
YY 
Y Y
 
YY  
%Y
#include <stdio.h>

void exibe_e_altera(int primeiro, int segundo, int terceiro)


{

printf("Valores originais da função %d %d %d \n",

primeiro, segundo, terceiro);

primeiro += 100;

segundo += 100;

terceiro += 100;

printf("Valores finais da função %d %d %d \n", primeiro,


segundo, terceiro);

void main(void)

int a = 1, b = 2, c = 3;

exibe_e_altera(a, b, c);

printf("Valores finais em main %d %d %d \n", a,b,c);

}Y

YY 
Y Y Y
 Y YY #YY Y
 Y Y #Y , Y

Y Y 

Y  #!Y " Y Y  #Y 
Y  Y 
 Y 
Y YO  #Y

 !Y

YY

 0<& 
 * 
6 YY Y
Y
Y Y  Y#YY 
YY
YY Y
Y
 Y
Y Y #!Y-YYY
Y Y

 Y Y  Y 
#Y Y

 Y Y Y Y  Y Y  
!Y 4
Y Y Y  #Y  Y 2Y 
 Y Y Y

 Y 
  Y  
Y  Y 
 Y Y Y 
Y Y 
 Y Y 
 
 !Y QY  Y

Y Y #YY Y 
Y
  Y 

Y Y
 YY Y 
 YY 
 
Y
Y
3  !Y " Y  Y   Y 
Y Y 
Y Y Y 
=
Y  Y 

 Y 
  Y
 
YY
=
Y
YY #Y Y Y
Y

2 !YVY
Y
Y Y

Y
YY Y
Y

2 YY Y YY Y
Y
Y Y  Y
 Y
Y Y Y 
Y Y Y 
=
!Y 4
Y  
Y Y Y Y Y 
Y

2 Y  Y
  Y
 YY 
YY
YY 
!Y4
Y Y  YY

YY


YY #YY
Y  , Y&Y 
 Y
 YY
YY
)+Y

 Y   Y  Y 
 Y  Y Y  #Y 

!Y 4
Y 
Y Y Y 
Y


2 Y  Y 

Y 
  
Y 
Y 4
 !Y 'Y N Y 
Y 4
 Y  Y Y
 Y Y4
 YY !Y-YY
Y
Y YY Y4
Y  Y
Y Y 
YY
!Y4
Y
 
YY 
YY Y 
YY Y
Y Y
  
Y 
YY

YY
YRSR!Y4
Y  
Y 

YY
YY #Y
Y
Y
YY YY4
YY

c  &  (    A '  !->7A?@ 


%>A?@

&A !->7A?@
Quando é necessário imprimir na tela um dado, um valor, uma string ou mesmo
um endereço de memória, usa-se a função „r Quando o programa usa a função
printf(), as informações que instrui printf() a imprimir são chamadas parâmetros ou
argumentos de printf(). A estrutura básica da função printf() é dada a seguir:
m   
   
    

A „Y Y „ contém tanto caracteres para serem impressos na tela como
códigos de formato que especificam como apresentar o restante dos argumentos.
Quando os programas trabalharem com variáveis, será possível usar printf() para exibir
os valores de cada variável. A função printf() suporta mais de um parâmetro. O primeiro
parâmetro precisa ser sempre uma string de caracteres. Pode-se fazer os parâmetros que
seguem a primeira string de caracteres serem números, expressões, variáveis, ou até
outras strings de caracteres. Quando for necessário que printf() exiba um valor ou uma
variável, é preciso fornecer informações sobre o tipo da variável dentro do primeiro
parâmetro. Além de especificar caracteres dentro do primeiro parâmetro, pode-se incluir
especificadores de formato, que instruem printf() como imprimir os outros parâmetros.
Esses especificadores de formato têm a forma de um sinal de porcentagem (%) seguido
por uma letra. Por exemplo, para exibir um valor inteiro, usa-se o %d. Da mesma forma
para exibir um valor em ponto flutuante, pode-se usar %f. A seguir, uma tabela com os
especificadores de formato:
  % <
%c Exibe um caractere
%d Exibe um inteiro em formato decimal
%i Exibe um inteiro
%e Exibe um número em notação científica (com e minúsculo)
%E Exibe um número em notação científica (com E maiúsculo)
%f Exibe um ponto flutuante em formato decimal
%g Usa %e ou %f, o que for menor
%G O mesmo que %g, só que um E maiúsculo é usado se o formato %e
for escolhido
%o Exibe um número em notação octal
%s Exibe uma string
%u Exibe um decimal sem sinal
%x Exibe um número em hexadecimal com letras minúsculas
%X Exibe um número em hexadecimal com letras maiúsculas
%% Exibe um sinal de %
%p Exibe um ponteiro
&(" 5
7  4  !
 <?@
 Para exibir valores do tipo  com printf(), usa-se o especificador de formato
ð O programa a seguir usa o especificador de formato %d para exibir valores e
variáveis do tipo int:

#include <stdio.h>
void main(void)
{
int idade = 41;
int altura = 182;
int peso = 80;
printf("Idade do usuario: %d peso: %d altura: %d \n", idade,
peso, altura);
printf("%d mais %d igual a %d \n", 1, 2, 1 + 2);
}

Y Uma observação importante é que muitos compiladores C tratam o especificador


de formato %i como idêntico a %d. No entanto, para criar-se novos programas , use o
especificador %d, pois %i é um legado do passado, e os compiladores futuros talvez
deixem de aceitá-lo.
&(" 5
  
+   
 Muitas vezes nos programas é preciso exibir um valor inteiro em seu formato
  Y Y ou   
 Y Y !O O especificador de formato ð (letra "o", não
zero) instrui printf() a exibir uma valor em   . Da mesma forma, ð e ð instruem
printf() a exibir uma valor em   
 , sendo que no primeiro caso em minúsculo
e no segundo imprime os valores em maiúsculo.
Veja a seguir um exemplo que utiliza estes especificadores de formato:
#include <stdio.h>
void main(void)
{
int valor = 255;
printf("O valor decimal %d em octal à %o \n", valor, valor);
printf("O valor decimal %d em hexadecimal à %x \n", valor,
valor);
printf("O valor decimal %d em hexadecimal à %X \n", valor,
valor);
}

& (" 5


7 4   
 Para exibir valores do tipo  Y  com a função printf(), deve-se usar o
especificador de formato ð. Se usar %d em lugar de %u, printf() tratará o valor
especificado como tipo int, provavelmente exibindo o valor incorreto. O exemplo a
seguir ilustra o uso dos dois especificadores, %d e %u.
#include <stdio.h>
void main(void)
{
unsigned int valor = 42000;
printf("Exibindo 42000 como unsigned %u \n", valor);
printf("Exibindo 42000 como int %d \n", valor);
}

&&(" 5
7   
 Para exibir valores do tipo Y  com a função printf(), deve-se usar o
especificador de formato ð . Se usar %d em lugar de %ld, printf() tratará o valor
especificado como tipo int, provavelmente exibindo o valor incorreto.
O exemplo a seguir ilustra o uso dos dois especificadores, %d e %ld:

#include <stdio.h>
void main(void)
{
long int um_milhao = 1000000;
printf ("Um milhão é %ld \n", um_milhao);
printf ("Um milhão é %d \n", um_milhao);
}

&)(" 5
7 A
 Para exibir valores do tipo r  com a função printf(), deve-se usar o
especificador de formato ðr. A seguir um exemplo que usa %f para exibir valores em
ponto flutuante.
#include <stdio.h>
void main(void)
{
float preco = 525.75;
float imposto_vendas = 0.06;
printf("O custo do item à %f \n", preco);
printf("O imposto sobre a venda do item à %f \n", preco *
imposto_vendas);
}

&.(" 5
7 2

Y Para exibir valores do tipo „ com a função printf(), deve-se usar o
especificador de formato ð . A seguir um exemplo que usa %c para exibir a letra A em
sua tela.Y
#include <stdio.h>
void main(void)
{
printf("A letra à %c \n", 'A');
printf("A letra à %c \n", 65);
}


&6  ("  5
   !  A     A

(  
Y Para exibir um valor em ponto flutuante em um formato exponencial com a
função printf(), deve-se usar o especificador de formato %e ou %E. A diferença entre
os dois é que %E instrui printf() a usar uma letra E maiúscula na saída.Y
#include <stdio.h>
void main(void)
{
float pi = 3.14159;
float raio = 2.0031;
printf("A área do círculo é %e \n", 2 * pi * raio);
printf("A área do círculo é %E \n", 2 * pi * raio);
}



&9(" 5
 ! A  
A função printf() também suporta os especificadores ð e ð para imprimir
valores em Y r  . Quando usa-se esses especificadores de formato, printf()
decide se deve usar o formato ðr ou ð , dependendo da técnica que exibirá a saída no
formato mais significativo para o usuário.
Veja o exemplo que ilustra o uso do especificador %g:Y
#include <stdi o.h>
void main(void)
{
printf("Exibir 0.1234 resulta em %g \n", 0.1234);
printf("Exibir 0.00001234 resulta em %g \n", 0.00001234);
}

&B(" %
  


Para exibir uma string de caracteres com a função printf(), deve-se usar o
especificador de formato %s.
A seguir um exemplo que usa %s para exibir uma string de caracteres:Y
#include <stdio.h>
void main(void)
{
char faculdade[255] = "Universidade Estadual Paulista";
printf("O nome da minha universidade é %s \n", faculdade);
}

&C(" ( 
 !  

Para exibir um endereço de ponteiro com a função printf(), deve-se usar o
especificador de formato %p.
A seguir um exemplo que usa %p para exibir um endereço de memória.Y
#include <stdio.h>
void main(void)
{
int valor;
printf("O endereço da variável valor é %p \n", &valor);
}
& # !
    5
   %       
%"

Em muitos programas é necessário que printf() exiba o sinal para os valores
positivos e negativos. Para instruir printf() a exibir um sinal de um valor, simplesmente
inclua um sinal de adição imediatamente após o % no especificador de formato. O
exemplo a seguir ilustra o uso do sinal de adição dentro do especificador de formato.
#include <stdio.h>
void main(void)
{
int neg_int = -5;
int pos_int = 5;
float neg_flt = -100.23;
float pos_flt = 100.23;
printf("Os valores inteiros são %+d and %+d \n",neg_int,
pos_int);
printf("Os valores em ponto flutuante são %+f %+f \n", neg_flt,
pos_flt);
}

&A
 5
  
 
Usando o especificador de formato ð, será possível instruir printf() a exibir um
número mínimo de caracteres. O dígito que for colocado após o % especifica o número
mínimo de caracteres que printf() usará para exibir um valor inteiro. Por exemplo, caso
seja especificado ð e o valor a ser exibido for 10, printf() predecerá o valor com três
espaços. Observe que o valor especifica o "
„Y


 de caracteres que a saída
consumirá. Se o valor a ser exibido requer mais caracteres do que o especificado,
printf() usará o número de caracteres que printf() requer para exibir o valor
corretamente. Veja um exemplo que ilustra este caso logo a seguir:
#include <stdio.h>
void main(void)
{
int valor = 5;
printf ("%1d \n", valor);
printf ("%2d \n", valor);
printf ("%3d \n", valor);
printf ("%4d \n", valor);
}

& #%   
 !
2D
 
No item anterior, foi visto como formatar uma saída instruindo printf() a exibir
um determinado número de dígitos. No caso anterior, printf() colocava espaços antes do
valor a ser exibido, mas é possível configurá-lo de tal maneira que ele exiba zeros antes
do valor ou caracter que é necessário exibir. Esses zeros são chamados de zeros de
preenchimento. Para instruir printf() a preencher um valor com zeros, coloca-se um 0
(zero) imediatamente após o % no especificador de formato, antes do número desejado
de dígitos. O exemplo abaixo ilustra o uso desta propriedade.
#include <stdio.h>
void main(void)
{
int valor = 5;
printf ("%01d \n", valor);
printf ("%02d \n", valor);
printf ("%03d \n", valor);
printf ("%04d \n", valor);
}

&&(" !
<   5
+ 0  
 Em muitos programas que apresentam valores octais ou hexadecimais, em
muitos casos é necessário que se preceda os valores em octal com um zero (0777, por
exemplo), e os hexadecimais com 0x (oxFF, por exemplo). Para instruir printf() a
preceder um valor octal ou hexadecimal com o prefixo apropriado, coloca-se um sinal 1
imediatamente após o % no especificador de formato. Veja o exemplo abaixo que ilustra
o uso do sinal #.
#include <stdio.h>
void main(void)
{
int valor = 255;
printf("O valo r decimal %d em octal é %#o \n", valor, valor);
printf("O valor decimal %d em hexadecimal é %#x \n", valor,
valor);
printf("O valor decimal %d em hexadecimal é %#X \n", valor,
valor);
}

&)A
 5
 ! A  
 No item 3.1.11 foi visto como formatar um valor inteiro colocando o número
desejado de dígitos imediatamente após o % no especificador de formato %d. Usando
uma técnica similar, printf() permite formatar a saída em ponto flutuante. Quando
formata-se um valor em ponto flutuante especifica dois valores. O primeiro valor diz a
printf() o número mínimo de caracteres a serem exibidos. O segundo valor diz a printf()
o número de dígitos a serem exibidos à direita do ponto decimal. O exemplo abaixo
ilustra esta técnica.
#include <stdio.h>
void main(void)
{
float valor = 1.23456;
printf ("%8.1f \n", valor);
printf ("%8.3f \n", valor);
printf ("%8.5f \n", valor);
}

&.A
 %(  
 No item anterior foi visto como usar o especificador de formato %f para
formatar valores em ponto flutuante. Usando técnicas de formatação similares, pode-se
instruir pintf() a exibir a saída em ponto flutuante em um formato exponencial. Veja o
exemplo a seguir que ilustra este caso.
#include <stdio.h>
void main(void)
{
float valor = 1.23456;
printf ("%12.1e \n", valor);
printf ("%12.3 e\n", valor);
printf ("%12.5e \n", valor);
}

&6E < *( 8


% !
 <?@
 Por padrão, quando for exibido o texto usando os caracteres de formatação,
printf() exibirá o texto justificado à direita. Dependendo do programa, algumas vezes é
necessário que printf() justifique o texto à esquerda. Para justificar o texto à esquerda,
coloque um sinal de subtração (-) imediatamente após o % no especificador de formato.
O exemplo a seguir ilustra o uso desta técnica de formatação.
#include <stdio.h>
void main(void)
{
int int_valor = 5;
float flt_valor = 3.33;
printf("Justificado à direita %5d valor \n", int_valor);
printf("Justificado à esquerda % -5d valor\n", int_valor);
printf("Justificado à direita %7.2f valor \n", flt_valor);
printf("Justificado à esquerda % -7.2f valor \n", flt_valor);
}



&9"   ( <
 A
 !
 <?@ 
 Muitas vezes por rapidez e para que o código torne-se mais enxuto pode-se
aproveitar dois ou mais especificadores de formato de printf(). Em tais casos,
simplesmente coloque cada um dos especificadores logo após o %. Veja um exemplo.

#include <stdio.h>
void main(void)
{
int int_valor = 5;
printf("Justificado à esquerda com sinal % -+3d\n", int_valor);
}

&B7
"2  

(   !
 <?@ 
 Quando trabalha-se com string de caracteres, pode-se usar caracteres especiais,
tais como tabulação, retorno do carro, ou alimentação de linha. A Linguagem C define
vários caracteres de escape (referenciados no Módulo 2 item 2.4.3) para facilitar para
você a inclusão de caracteres especiais dentro de uma string. Um exemplo é o uso do
caracter de nova linha (\n) para avançar a saída para o início da próxima linha.
printf("Linha 1 \nLinha2\nLinha 3\n");

&C0 
  >F
 

8 !
 <?@(" 
 Quando usa-se o especificador de formato %n, printf() atribuirá à uma variável
(passada por ponteiro) um contador do número de caracteres que printf() exibiu.
#include <stdio.h>
void main(void)
{
int primeiro_conta;
int segundo_conta;
printf("Universidade%n Estadual Paulista%n \n",&primeiro_conta,
&segundo_conta);
printf("Primeiro conta %d Segundo conta %d \n", primeiro_conta,
segundo_conta);
}

&4  5
 - 
 !
 <?@
 Usar o especificador de formato %n é um modo de garantir que printf() teve
sucesso ao exibir sua saída. Além disso, quando printf() termina, ele retorna o número
total de caracteres que escreveu. Se printf() encontrar um erro, retornará a constante
EOF (que como será visto no módulo sobre sistema de arquivo, indica o fim de um
arquivo). O exemplo a seguir, usa o valor de retorno de printf() para garantir que printf()
foi bem sucedido.
#include <stdio.h>
void main(void)
{
int result;
result =
printf("Universidade Estadual Paulista \n");
if (result == EOF)
fprintf(stderr, "Erro dentro de printf \n");
}

&A %>A?@
A função  rYYé uma das funções de entrada de dados da Linguagem C, que
pode ser usada para ler virtualmente qualquer tipo de dado inserido por meio do teclado,
freqüentemente ela é usada para a entrada de números inteiros ou de ponto flutuante. A
forma geral da função  rYYé:
   
   
   

Os especificadores de formato de entrada são precedidos por um sinal ðYe dizem


à função  rYYqual tipo de dado deve ser lido em seguida. Esses códigos são listados
na tabela a seguir.
  % <
%c Lê um único caractere
%d Lê um decimal inteiro
%i Lê um decimal inteiro (não pode ser octal ou hexadecimal)
%u Lê um decimal sem sinal
%e Lê um número em ponto flutuante com sinal opcional
%f Lê um número em ponto flutuante com ponto opcional
%g Lê um número em ponto flutuante com expoente opcional (double)
%o Lê um número em base octal
%s Lê uma string
%x Lê um número em base hexadecimal
%p Lê um ponteiro
Os caracteres de conversão #Y , , Y e Y podem ser precedidos por Y para
indicarem que um apontador para „Yao invés de Yaparece na lista de argumentos,
ou por Y (letra ele) para indicar que um apontador para Y aparece na lista de
argumentos. Semelhantemente, os caracteres de conversão # rYe Ypodem ser precedidos
por Y(letra ele) para indicarem que um apontador para  Yao invés de r Yestá na
lista de argumentos.
A cadeia de formato geralmente contém especificações de conversão, que são
usadas para controlar a conversão da entrada. A cadeia de formato pode conter:
:Y : espaços, tabulações e novas linhas, que serão ignorados;
:Y : caracteres comuns (não %), que devem combinar com o próximo
caractere não espaço do fluxo de entrada;
:Y : especificações de conversão, consistindo no caractere %, um
caractere /Yopcional de supressão de atribuição, um número opcional especificando um
tamanho máximo do campo, um You Yopcional indicando o tamanho do destino, e um
caractere de conversão.
&4  

 % <?@8 %
0 

Um caractere que não seja um espaço em branco faz com que a função scanf( )Yleia
e descarte o caractere correspondente. Por exemplo, $ð#ð%Yfaz com que a função scanf()Y
leia um inteiro, então, leia uma vírgula (que será descartada) e, finalmente, leia outro
inteiro. Se o caractere especificado não é encontrado, a função  rYYterminará. Pode-se
usar esta técnica para separa os especificadores de formato, tornando o código mais legível.

#include <stdio.h>
void main(void)
{
int a,b;
scanf("%d,%d", &a, &b);
}

&# 5
 5
$  
Todas as variáveis usadas para receber valores por meio da função scanf()Y
deverão ser passadas pelos seus endereços. Por exemplo, para ler um inteiro em uma
variável , poderia usar a seguinte chamada à função scanf():
#include <stdio.h>
void main(void)
{
int count;
scanf("%d ", &count);
}

&  %


  


As strings serão lidas em vetores (cadeias de caracteres) e o nome do vetor é o
endereço do primeiro elemento do vetor. Então, para ler uma string no vetor de
caracteres 
, deve-se usar o seguinte comando: 
#include <stdio.h>
void main(void)
{
char nome[40];
scanf("%s", nome);
}

Nesse caso, 
Yjá é um endereço e não precisa ser precedido pelo operador &.
&&A
 ( 
 % <?@
Os itens de dados de entrada devem ser separados por espaços, tabulações ou
novas linhas. Pontuações como vírgula, ponto-e-vírgula e semelhantes não contam
como operadores. Isso significa que scanf(³%d%d´, &r, &c); aceitará uma entrada dos
números &Y '&, mas falhará com &#'&. Como na função „rY @, os códigos de
formato da função  rY Y devem ser correspondidos na ordem com as variáveis que
estão recebendo a entrada na lista de argumento.
Um /colocado depois do % e antes do código de formato lerá um dado de um
tipo especificado, mas suprimirá a sua atribuição. Assim, scanf(³%d%*c%d´, &x, &y);
dando-se a entrada &('&, colocará o valor 10 em Y descartando o sinal de divisão, e
dará a )Yo valor 20.
Ainda que espaços, tabulações e novas linhas sejam usados como separadores
de campos, quando da leitura de um único caractere, esses últimos são lidos como
qualquer outro caractere. Por exemplo, com uma entrada de $Y)´; scanf(³%c%c%c´,
&a, &b, &c); retornará com o caractere ³x´ em a, um espaço em Y e o caractere ³y´
em c.

&)0 
  >F
c 



Os comandos de formato podem especificar um campo modificador de
comprimento máximo. Esse modificador é um número inteiro colocado entre o sinal ðY
e o código de comando de formato, que limita o número de caracteres lidos para
qualquer campo. Por exemplo, para ler não mais que 20 caracteres em 
, você pode
escrever:
#include <stdio.h>
void main(void)
{
char str[40];
<span lang=EN-US style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-fa
Y

c )#( 

  A  
 

)0 
<
A declaração r é usada quando é necessário testar em um programa duas ou
mais condições. Isto permite ao programador o desenvolvimento de programas
complexos. A forma geral da declaração rYé:
if (condição)
{
comandos;
}
else
{
comandos;
}

A cláusula  Yé opcional. Se *+Yfor verdadeira (qualquer coisa diferente


de 0), o bloco que forma o destino de rY será executado; caso contrário o bloco que
forma o destino de  Yserá executado (desde que exista  ).
Lembre-se que somente o código associado a rYou o código associado a  Yserá
executado, nunca os dois. O destino dos dois, rYe  , pode ser um comando simples ou
um bloco de comandos.
O comando rY será demonstrado através de um programa simples que converte
bases numéricas. Este programa será capaz de apresentar as seguintes conversões:
:Y : Decimal para Hexadecimal;
:Y : Hexadecimal para Decimal.
O programa permitirá que primeiro seja selecionado o tipo de conversão a partir
de um menu e, então, solicitará o número a ser convertido.
#include <stdio.h>
void main()
{
int opcao;
int valor;
printf (³Converter: \n´);
printf (³1: decimal para hexadecimal \n´);
printf (³2: hexadecimal para decimal \n´);
printf (³\nInforme sua opção: ´);
scanf (³%d´, &opcao);
if (opcao == 1)
{
printf (³\nInforme o valor em decimal: ´);
scanf (³%d´, &valor);
printf (³%d em hexadecimal e: %x´, valor, valor);
}
if (opcao == 2)
{
printf (³\nInforme o valor em hexadecimal: ´);
scanf (³%x´, &valor);
printf (³%x em decimal e: %d´, valor, valor);
}
}



)#4  0 
( 
 possível associar um  Y com qualquer r. Com esta declaração podemos
acrescentar ao teste condicional várias opções de escolha. Se a expressão condicional
associada a rYé verdadeira, a instrução ou bloco de instruções associada será executada.
Se for falsa, então a instrução ou bloco de instruções do  Y será executada. O
programa seguinte demonstra este princípio fundamental:
#include <stdio.h>

void main()
{
int i;
printf (³Informe um número: ´);
scanf (³%d´, &i);
if (i < 0) printf (³O número é negativo´);
else printf (³O número é positivo ou nulo´);
}

)+(   <#( #<


Uma construção comum em programação é o encadeamento r  r. O
seguinte exemplo ilustra esta construção:
if (condição)
{
comandos;
}
else if (condição)
{
comandos;
}
else if (condição)
{
comandos;
}
else
{
comandos;
}

As expressões condicionais serão avaliadas de cima para baixo. Assim que uma
condição verdadeira é encontrada, o bloco associado a ela será executado, e o resto do
encadeamento é ignorado. Se nenhuma das condições for verdadeira, então o  Yfinal
será executado.
Se o  Y final não estiver presente e todas as outras condições forem falsas,
então nenhuma ação será realizada.
Pode-se usar o encadeamento r  rY para implementar o programa de
conversão de base numérica desenvolvido anteriormente. Na versão original, cada
declaração rY era avaliada sucessivamente, mesmo se uma das declarações anteriores
tivesse êxito. Ainda que não haja grande significado neste caso, a avaliação redundante
de todos os r não é muito eficiente ou elegante. O seguinte programa resolve este
problema. Nessa versão de encadeamento r  r, tão logo uma declaração rY é
satisfeita, o resto das declarações é ignorado.

/* Programa de conversão de base numérica ± if-else-if


decimal ---> hexadecimal
hexadecimal ---> decimal
*/

#include <stdio.h>

void main()
{
int opcao;
int valor;

printf (³Converter: \n´);


printf (³1: decimal para hexadecimal \n´);
printf (³2: hexadecimal para decimal \n´);
printf (³\nInforme sua opção: ´);
scanf (³%d´, &opcao);

if (opcao == 1)
{
printf (³ \nInforme o valor em decimal: ´);
scanf (³%d´, &valor);
printf (³%d em hexadecimal e: %x´, valor, valor);
}
else if (opcao == 2)
{
printf (³ \nInforme o valor em hexadecimal: ´);
scanf (³%x´, &valor);
printf (³%x em decimal e: % d´, valor, valor);
}
else
{
printf (³ \nA opção escolhida é inválida.´)
}
}

) (
  
Algumas vezes, iniciantes na linguagem C confundem-se pelo fato de que
qualquer expressão válida na linguagem C pode ser usada para controla a declaração r.
Isto é, o tipo de expressão não precisa se restringir àquelas envolvendo operadores
relacionais e lógicos. Só é requerido que a expressão resulte em um valor zero ou não
zero. Por exemplo, este programa lê dois inteiros do teclado e mostra o quociente. Para
evitar um erro de divisão por zero, uma declaração rYé usada para controlar o segundo
número.
#include <stdio.h>
void main()
{
int a, b;
printf (³Informe dois números: ´);
scanf (³%d%d´, &a, &b);
if (b) printf (³%d \n´, a/b);
else printf (³Não posso dividir por zero \n´);
}

Essa abordagem funciona porque, se b for zero, a condição controlando o rY é


falsa e a instrução  Yé executada. Caso contrário, a expressão é verdadeira (não zero)
e a divisão é realizada. Não é necessário escrever uma declaração rYcomo esta
if (b != 0) printf (³%d \n´, a/b);

porque é redundante.
)&<   2 
Um dos muitos aspectos que causam confusão na declaração r, em qualquer
linguagem de programação, são os fs aninhados. Um rYaninhado é uma declaração rY
que é objeto de um rY ou um e. Os fs aninhados são incômodos por poderem
dificultar saber qual  Yestá associado a qual f.
Considere este exemplo:
if (x)
if (y) printf (³1´);
else printf (³2´);

Em C, o  Yé ligado ao rYmais próximo dentro do mesmo bloco de código que


já não tenha uma declaração  Y associada a ele. Neste caso o  Y é associado à
declaração r)).
Para fazer com que  Y seja associado à declaração r, deve-se usar chaves
para sobrepor a sua associação normal, como mostrado aqui:
if (x)
{
if (y) printf (³1´);
}
else printf (³2´);

O  Yagora está associado ao r), já que ele não é parte do bloco de código do
r)).
)0 
A

 Uma operação que vários programas executarão comumente é repetir um
conjunto de comandos um número específico de vezes. Por exemplo, pode-se querer
calcular as notas dos exames de 30 alunos ou soar três vezes o alto-falante interno do
computador. Para auxiliar programas a repetir um ou mais comandos um certo número
de vezes, a Linguagem C fornece o comando r„.
for(valor_inicial; condição_final; valor_incremento)
comando;

Quando um programa repetir comandos um número específico de vezes,


normalmente usará uma „, Y  Y „ , que contará o número de vezes que for
executado os comandos. O comando r„ contém quatro seções. A seção  „ 
atribui à „, Y Y „ o valor inicial da variável, que é, na maioria das vezes, 0
ou 1. A seção *+r normalmente testa o valor da „, Y  Y „ para
determinar se o programa executou os comandos um número desejado de vezes. A
seção  „ „
 normalmente adiciona o valor 1 para a „, Y  Y „
toda a vez que os comandos são executados. Finalmente a quarta seção do comando for
é o 
ou comandos especificados. O comando r„ é geralmente chamado de *Y
r„. Considere o seguinte *Yr„, ele exibirá os números de 1 a 10 na sua tela:
for(contador=1; contador <= 10; contador++)
printf("%d \n", contador);

Para compreender melhor o processamento do laço r„ execute em seu


compilador o seguinte programa:
#include <stdio.h>

void main(void)
{
int contador;

for (contador = 1; contador <= 5; contador++)


printf("%d ", contador);

printf("\nIniciando o segundo laco \n");

for (contador = 1; contador <= 10; contador++)


printf("%d ", contador);

printf("\nIniciando o terceiro laco \n");

for (contador = 100; contador <= 5; contador++)


printf("%d ", contador);
}
Como pode-se verificar, o primeiro *Y r„ exibe os números de 1 até 5. O
segundo laço exibe os valores de 1 até 10. O terceiro laço não exibe nenhum valor. Se
for examinado com atenção, será visto que o programa inicialmente atribui à variável de
controle do laço o valor 100. Quando o comando r„ testa o valor, o *Y r„ atende
imediatamente à condição final, de modo que o laço não é executado.
)!
  A
 +   
 Como foi visto no item anterior, o laço for usa três seções dentro do comando
for: uma inicialização, um teste e um incremento:
for(inicialização; teste; incremento)

Dependendo do programa, algumas vezes pode não ser necessário o uso de cada
uma das seções do comando for. Por exemplo, se já foi atribuido o valor 0 à variável
conta, pode-se pular a seção de inicialização do laço. Depois, para exibir os números de
0 até 999, o laço conterá o seguinte:
for(; conta <1000; conta++)
printf("%d", conta);

Y No entanto, se for omitido uma das seções do laço for, precisa-se incluir o
ponto-e-vírgula correspondente. Por exemplo, o laço for a seguir omite as seções de
inicialização e de incremento:
for(; conta < 1000; )
printf("%d", conta++);

Y Da mesma forma, o comando for à seguir ficará em execução perpetuamente.


Este é o chamado laço infinito:Y
for (; ; ; )
/*comando*/



)
 >
 No passado, quando os programadores queriam que seus programas fizessem
uma breve pausa, talvez para exibir alguma mensagem, eles colocavam um *Y  ou
"não faz nada" em seus programas. Por exemplo, o seguinte laço for não faz nada 100
vezes:
for(contador=1; contador <= 100; contador++)
; /* não faz nada */

Y Quando se coloca um laço nulo nos programas, a Linguagem C efetuará a


inicialização do laço, e, depois, repetidamente, testará e incrementará a variável de
controle até que a variável de controle atenda a condição final. O teste repetido do laço
consome tempo do processador, o que faz o programa retardar. Se o programa precisar
de um retardo maior, você poderá aumentar a condição final:
for(contador=1; contador <= 10000; contador++)
; /* não faz nada */
Usar as técnicas de retardo, tais como o laço nulo, poderá causar problemas.
Primeiro, se o programa estiver rodando em um computador 286, 386 ou 486, a duração
do retardo diferirá simplesmente devido à diferença de velocidade entre os diferentes
microprocessadores. Segundo, se o programa estiver rodando em um ambiente
multitarefa, tal como o Windows, OS/2 ou Unix, os laços "não fazem nada" consomem
tempo que o processador poderia estar gastando fazendo trabalho importante em outro
programa.
) 
  < 
 Quando são usados laços for, precisa-se garantir que o laço atenderá à sua
condição final. Caso contrário, o laço continuará sua execução para sempre. Esses laços
intermináveis são chamados laços infinitos. Na maioria dos casos, os laços infinitos
ocorrem como resultado de erro na programação. Por exemplo, considere o seguinte
laço:
for(i = 0; i <100; i++)
{
printf("%d", i);
resultado = valor * --i; /*causa do erro*/
}

Y Como pode-se verificar, o segundo comando do laço decrementa o valor da


variável de controle i. Especificamente, o laço decrementa o valor para -1, e, depois,
incrementa o valor para 0. Como resultado, o valor nunca atinge 100, de modo que o
laço não termina. Quando o programa entra em um laço infinito, pode-se pressionar
Ctrl+C para finalizar o programa.
O programa a seguir ilustra um laço infinito:
#include < stdio.h>
void main(void)
<span lang=EN-US style='
Y

c .c
G    
.
  c
G 
Muitas vezes em programas, é necessário que uma variável contenha muitos
valores. Por exemplo, a variável  pode controlar as notas obtidas por 100 alunos em
um exame. Da mesma maneira, a variável  ,„ poderia controlar os salários de cada
funcionário em uma companhia. Uma matriz é uma estrutura de dados que pode
armazenar múltiplos valores do mesmo tipo. Por exemplo, pode-se criar uma matriz que
possa conter 100 valores do tipo int e uma Segunda matriz com 25 valores do tipo float.
Todo valor que você atribui a uma matriz precisa ser do mesmo tipo que o tipo
da matriz. Neste módulo será mostrado como criar e trabalhar com matrizes em
programas. Com o tempo, após o uso de matrizes, ficará claro como é simples o uso de
matrizes.

.0 
 c
G
Para declarar uma matriz, precisa-se especificar o tipo desejado (tal como int,
float ou double), bem como o tamanho da matriz. Para especificar o tamanho de uma
matriz, coloca-se o número de valores que a matriz pode armazenar dentro de colchetes
após o nome da matriz. Por exemplo, a declaração à seguir cria uma matriz chamada
, que pode armazenar 100 notas de exame do tipo int:
int notas [100];

De forma similar, a seguinte declaração cria uma matriz do tipo float, que
contém 50 salários:
float salarios [50];

Quando uma matriz é declarada, a Linguagem C aloca memória suficiente para


conter todos os elementos. O primeiro item está na posição 0. Por exemplo, nas matrizes
 e  „, os comandos a seguir atribuem os valores 80 e 35000 aos primeiros
elementos da matriz:
notas[0] = 80;
salarios[0] = 35000;

Como o primeiro elemento da matriz inicia no deslocamento 0, o último


elemento da matriz ocorre uma posição antes do tamanho da matriz. Dadas as matrizes
anteriores, os comandos a seguir atribuem valores ao último elemento de cada matriz:
notas[99] = 65;
salarios[49] = 250000;

.   
    - 8     
G    
c
G
Ao declarar uma matriz, o compilador aloca memória suficiente para conter o
número de valores especificado. A quantidade real de memória que o compilador aloca
depende do tipo da matriz. Por exemplo, uma matriz de 100 elementos do tipo int
normalmente irá requerer 100*2 ou 200 bytes de memória. Por outro lado, uma matriz
de 100 elementos do tipo float irá requerer 100*4 bytes ou 400 bytes. O programa
abaixo, usa o operador sizeof para exibir a quantidade de memória que os diferentes
tipos de matrizes requerem:
#include <stdio.h>

void main(void)
{
int notas[100];
float salar[100];
char string[100];

printf("Memoria para conter int notas[100] %d bytes \n",


sizeof(notas));
printf("Memoria para conter float salar[100] %d bytes \n",
sizeof(salar));
printf("Memoria para conter char s tring[100] %d bytes \n",
sizeof(string));
}

.&# G c


G
Muitos programas em Linguagem C inicializam as strings de caracteres como
segue:
char titulo[] = "UNESP - Ilha Solteira";
char secao[64] = "Matrizes";

No primeiro caso, o compilador alocará 22 bytes para armazenar a string. No


segundo, o compilador alocará uma matriz de 64 bytes, inicializando os primeiro 8
caracteres com as letras "Matrizes" e o caracter NULL. A maioria dos compiladores
também inicializará as posições de bytes restantes com NULL. Quando declara-se
matrizes de outros tipos, pode inicializar matrizes da mesma forma. Por exemplo, o
comando a seguir inicializa a matriz de inteiros  com os valores 80, 70, 90, 85 e
80:
int notas[5] = {80, 70, 90, 85, 80};

Quando atribui-se valores iniciais a uma matriz, é necessário delimitar os valores


por abre e fecha chaves ( {} ). No caso anterior, o tamanho da matriz é igual ao número
de valores atribuídos. O comando a seguir, no entanto, atribui quatro valores de ponto
flutuante a uma matriz que pode armazenar 64 valores:
float salar[64] = {25000.0, 32000.0; 44000.0, 23000.0};

Dependendo do compilador, ele pode atribuir 0 aos elementos aos quais o


programa não atribui valores explícitos. No entanto, como regra, não se deve assumir
que o compilador inicializará os outros elementos. Além disso, se não for especificado
um tamanho de matriz, o compilador alocará memória suficiente para conter somente os
valores que você especificar. Por exemplo, a seguinte declaração de matriz cria uma
matriz grande o suficiente para conter três valores do tipo long:
long planetas[] = {1234567L, 654321L, 1221311L};

.)  (   c


G
Os valores armazenados em uma matriz são chamados elementos de matriz. Para
acessar um elemento da matriz, você especifica o nome da matriz e o elemento que
deseja. O programa a seguir, inicializa a matriz  e depois usa printf para exibir os
valores dos elementos:
#include <stdio.h>

void main(void)
{
int notas[5] = {80, 70, 90, 85, 80};

printf("Valores da Matriz \n");


printf("notas[0] %d \n", notas[0]);
printf("notas[1] %d \n", notas[1]);
printf("notas[2] %d \n", notas[2]);
printf("notas[3] %d \n", notas[3]);
printf("notas[4] %d \n", notas[4]);
}

..!


 (   c


G
Quando se referencia muitos elementos de uma matriz, especificar números para
cada elemento da matriz individualmente pode ser demorado e tedioso. Como uma
alternativa, os programas podem usar uma variável para referenciar os elementos da
matriz. Por exemplo, assumindo que a variável i contenha o valor 2, o comando a seguir
atribuiria o valor 80 a matriz[2]:
i = 2;
matriz[i] = 80;

O código a seguir usa a variável  e um laço r„ para exibir os elementos da


matriz :
#include <stdio.h>

void main(void)
{
int notas[5] = {80, 70, 90, 85, 80};
int i;

printf("Valores da Matriz \n");


for (i = 0; i < 5; i++)
printf("notas[%d] %d \n", i, notas[i]);
}

.64     !


0 < 
 c
G
Como visto, quando os programas trabalham com matrizes, é necessário
especificar o tamanho da matriz. Por exemplo, o programa a seguir declara uma matriz
de cinco valores e depois usa um laço for para exibir os valores da matriz:
#include <stdio.h>

void main(void)
{
int valores[5] = {80, 70, 90, 85, 80};
int i;

for (i = 0; i < 5; i++)


printf("valores[%d] %d \n", i, valores[i]);
}
Por exemplo, suponha que seja necessário alterar o código anterior de tal forma
que ele suporte 10 valores. Precisará alterar não somente a declaração da matriz, mas
também o laço for. Quanto mais alterações forem feitas em um programa, maiores as
chances de errar. O programa a seguir declara uma matriz com base na constante
TAM_MATRIZ. Como se vê, o programa não somente usa a constante para declarar a
matriz, mas também usa a constante como a condição final para o laço for:
#include <stdio.h>
#define TAM_MATRIZ 5

void main(void)
{
int valores[TAM_MATRIZ] = {80, 70, 90, 85, 80};
int i;

for (i = 0; i < TAM_MATRIZ; i++)


printf("valores[%d] %d \n", i, valores[i]);
}

Se mais tarde for necessário alterar o tamanho da matriz, poderá alterar o valor
atribuído à constante TAM_MATRIZ para que o programa automaticamente atualize os
laços que controlam a matriz como o tamanho da matriz.
.9!  c
GA 
Quando declara-se uma função que trabalha com um parâmetro matriz, precisa
informar o compilador. Por exemplo, o seguinte programa usa a função  
„-
para exibir os valores em uma matriz. Como pode-se ver, o programa passa para a
função tanto a matriz como o número de elementos que a matriz contém, como
mostrado a seguir:
#include <stdio.h>
void exibe_matriz(int valores[], int num_de_elementos)
{
int i;
for (i = 0; i < num_de_elementos; i++)
printf("%d \n", valores[i]);
}
void main(void)
{
int notas[5] = {70, 80, 90, 100, 90};
exibe_matriz(notas, 5);
}
Quando uma função recebe uma matriz como parâmetro, o programa não precisa
especificar o tamanho da matriz na declaração do parâmetro. No caso da função
   „ , os colchetes após o nome da variável  „ informam o compilador de
que o parâmetro é uma matriz. Sabendo que o parâmetro é uma matriz, o compilador
não se preocupa com o tamanho da matriz que o programa passa para a função.
.B- $   c
G A '
No item anterior, foi visto que ao declarar o parâmetro formal para uma matriz,
não é necessário declarar o tamanho da matriz. Em vez disso, pode-se especificar
somente o abre e fecha colchetes. O programa a seguir passa três matrizes diferentes (de
diferentes tamanhos) para a função    „ :

#include <stdio.h>

void exibe_matriz(int valores[], int num_de_elementos)


{
int i;

printf("Prestes a exibir %d valores \n",num_de_elementos);


for (i = 0; i < num_de_elementos; i ++)
printf("%d \n", valores[i]);
}

void main(void)
{
int notas[5] = {70, 80, 90, 100, 90};
int conta[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Y

c 6!  
 
6!  
 ( 
 
Como já foi visto, uma variável é o nome de uma posição na memória que pode
armazenar um valor de um determinado tipo. Os programas referenciam cada posição
na memória usando um endereço exclusivo. Um  „ é uma variável ou um valor
que contem um endereço. A Linguagem C utiliza muito os ponteiros. Quando se passa
matrizes ou string para as funções, o compilador C passa um ponteiro. Da mesma
forma, quando uma função precisa alterar o valor de um parâmetro, o programa deve
passar para a função um ponteiro para o endereço de memória da variável.

60 
  ( 
 5
$ 
Um  „ é um endereço de uma posição na memória. Quando os
programas trabalham com matrizes (e strings), o programa trabalha com um ponteiro
para o primeiro elemento da matriz. Quando os programas precisarem determinar o
endereço de uma variável, deverão usar o operador de endereço da Linguagem C
³&´.
Por exemplo, o programa a seguir usa o operador de endereço para exibir o
endereço de várias variáveis diferentes:
#include <stdio.h>

void main(void)
{
int conta = 1;
float salario = 40000.0;
long distancia = 1234567L;

printf("O endereço de conta à %x \n", &conta);


printf("O endereço de salario à %x \n", &salario);
printf("O endereço de distancia à %x \n", &distancia);
}
6   
c
G !  
 
Já foi visto anteriormente que um compilador C trata as matrizes como
ponteiros. Por exemplo, quando um programa passa uma matriz para uma função, o
compilador passa o endereço inicial da matriz.
O programa a seguir exibe o endereço inicial de várias matrizes diferentes:
#include <stdio.h>
void main(void)
{
int conta[10];
float salarios[5];
long distancia[10];
printf("O endereço da matriz conta à %x \n", conta);
printf("O endereço da matriz salarios à %x \n", salarios);
printf("O endereço da matriz distancia à %x \n", distancia);
}


6&  +

 ( 
?H@c
G
Se o  „„Y Y  „ * for aplicado a uma matriz, a Linguagem C retornará
o endereço inicial da matriz. Portanto, aplicar o operador de endereço a uma matriz é
redundante. O programa a seguir exibe o endereço inicial de uma matriz, seguido pelo
ponteiro que o operador de endereço retorna:
#include <stdio.h>

void main(void)
{
int conta[10];
float salarios[5];
long distancias[10];

printf("O endereço da matriz conta à %x &conta à %x \n",


conta, &conta);
printf("O endereço da matriz salarios à %x &conta à %x \n",
salarios, &salarios);
printf("O endereço da matriz distancias à %x &distancias Ã
%x\n", distancias, &distancias);
}

6)0 
 5
$  !  
 
À medida que os programas tornarem-se mais complexos, ponteiros são usados
com muita freqüência. Para armazenar ponteiros, os programas precisam declarar
variáveis ponteiros. Para declarar um ponteiro, precisa-se especificar o tipo do valor ao
qual o ponteiro aponta (tal como , r , „, etc.) e um asterisco (*) antes do nome
da variável. Por exemplo, o comando a seguir declara um ponteiro para um valor do tipo
:
int *iptr;

Como qualquer variável, precisa-se atribuir um valor a uma variável ponteiro


antes de poder usar o ponteiro dentro do programa. Quando atribui-se um valor a um
ponteiro, realmente atribui um endereço. Assumindo que anteriormente tenha-se
declarado  , o comando a seguir atribui o endereço da variável conta ao ponteiro
„:
iptr = &conta; /* Atribui o endereço de conta a iptr */

O programa a seguir declara a variável ponteiro „ e atribui ao ponteiro o


endereço da variável . O programa então exibe o valor da variável ponteiro,
juntamente com o endereço de :
#include <stdio.h>

void main(void)
{
int *iptr; /* Declara variavel ponteiro */
int conta = 1;

iptr = &conta;
printf("Valor de iptr %x Valor de conta %d Endereço de conta
%x\n", iptr, conta, &conta);
}


6.0
<
 !  

Desreferenciar um ponteiro é o processo de acessar o valor de uma posição de
memória específica. Para desreferenciar o valor de um ponteiro, usa-se o operador
 „ Y  Y „ *+Y .OY Por exemplo, o comando „r a seguir exibe o valor
apontado pelo ponteiro inteiro „:
printf(³O valor apontado po iptr é %d \n´, *iptr);

Da mesma forma, o comando a seguir atribui o valor apontado pela variável „
para a variável :
conta = *iptr;

Finalmente, o comando a seguir atribui o valor 7 à posição de memória apontada


por „:
*iptr = 7;

664  5
 !  

O programa a seguir atribui ao ponteiro Y„ o endereço da variável . O
programa depois exibe o valor do ponteiro e o valor armazenado na posição apontada
pelo ponteiro (o valor „).
O programa então modifica o valor apontado pelo ponteiro, como mostrado
aqui:
#include <stdio.h>

void main(void)
{
int contador = 10;
int *iptr; /* Declara valor do ponteiro */

iptr = &contador; /* Atribui o endereço */


printf("Endereço em iptr %x Valor em *iptr %d \n", iptr, *iptr);

*iptr = 25; /* Altera o valor na memória */

printf("Valor de contador %d \n", contador);


}

69!  
 !
I 
  A 
O Módulo de Funções examina em detalhes o processo de passar parâmetros
para as funções. Quando for necessário alterar o valor de um parâmetro, deverá passar
para a função um ponteiro para um parâmetro. O programa a seguir usa os ponteiros
para dois parâmetros do tipo  para permutar os valores das variáveis, como mostrado
a seguir:
#include <stdio.h>

void troca_valores(int *a, int *b)


{
int temp;

temp = *a; /* Armazena temporariamente o valor */


/* apontado por a */
*a = *b; /* Atribui o valor de b a a */
*b = temp; /* Atribui o valor de a a b */
}

void main(void)
{
int um = 1, dois = 2;

troca_valores(&um, &dois);

printf("um contém %d dois contém %d \n", um, dois) ;


}

Como pode ser visto, dentro da função, os comandos desreferenciam os


ponteiros usando o operador de indireção (*). O programa passa o endereço de cada
variável para a função usando o operador de endereço (&).

6B
J !  
 
Um ponteiro é um endereço que aponta para um valor de um determinado tipo
na memória. Nos termos mais simples possíveis, um ponteiro é um valor que aponta
para uma posição de memória específica. Se somar-se o valor 1 a um ponteiro, o
ponteiro apontará para a próxima posição de memória. Se somar-se 5 ao valor de um
ponteiro, o ponteiro apontará para a posição de memória de cinco posições adiante do
endereço atual. No entanto, a aritmética de ponteiro não é tão simples quanto parece.
Por exemplo, assuma que um ponteiro contenha o endereço 1000. Se fosse somado 1 ao
ponteiro, poderia se esperar que o resultado fosse 1001. No entanto, o endereço
resultante depende do tipo de ponteiro. Por exemplo, se fosse somado 1 a um ponteiro
do tipo char (que contém 1000), o endereço resultante será 1001. Se fosse somado 1 a
um ponteiro do tipo int (que requer dois bytes na memória), o endereço resultante será
1002. Quando for efetuada a aritmética de ponteiro é necessário ter em mente o tipo de
ponteiro. Além de somar valores aos ponteiros, os programas poderão subtrair valores
ou somar e subtrair dois ponteiros.
6C 
   0 
  !  

Uma das operações mais comuns com ponteiros é o incremento e o decremento
do valor de um ponteiro para apontar para a próxima posição ou para a posição anterior
na memória. O programa a seguir atribui o endereço inicial de uma matriz de valores
inteiros ao ponteiro „. O programa depois incrementa o valor do ponteiro para exibir
os cinco elementos que a matriz contém:
#include <stdio.h>

void main(void)
{
int valores[5] = {1, 2, 3, 4, 5};
int contador;
int *iptr;

iptr = valores;

for (contador = 0; contador < 5; contador++)


{
printf("%d \n", *iptr);
iptr++;
}
}

6#!


%
   !  

Uma string é uma matriz de caracteres terminada pó NULL. O programa a
seguir usa a função  „ para exibir uma string de caracteres usando um
ponteiro:
#include <stdio.h>

void exibe_string(char *string)


{
while (*string)
putchar(*string++);
}

void main(void)
{
exibe_string("Unesp Ilha Solteira");
}

Como pode ser visto, a função  „ declara a variável string como um
ponteiro. Usando o ponteiro, a função simplesmente percorre os caracteres da string até
encontrar o caractere NULL. Para exibir o caractere, a função  „ primeiro
desreferencia o endereço do ponteiro (obtendo o caractere). Em seguida, a função
incrementa o ponteiro para apontar para o próximo caractere na string.

6#A ' 8 



!  
 
O valor que uma função retorna é sempre do tipo declarado no protótipo ou
cabeçalho da função. Além de retornar esses tipos básicos, as funções podem declarar
ponteiros para os valores. Por exemplo, a função r , que a maioria das funções da
Linguagem C usam para abrir um canal de arquivo, retorna um ponteiro para uma
estrutura do tipo FILE, como mostrado aqui:
FILE *fopen(const char *nomecaminho, const char *modo);

6 
 A 8 

!  

O programa a seguir cria uma função chamada „
 que converte
todos os caracteres de uma string para maiúsculas e depois retorna um ponteiro para
uma string:
#include <stdio.h>
#include <ctype.h>
char *string_maiusc(char *string)
{
char *ender_inicial, *temp;
ender_inicial = temp = string;
while (*string)
*(temp++) = toupper(*string++);
return(ender_inicial);
}
void main(void)
{
char *titulo = "UNESP Ilha Solteira";
char *string;
string = string_m aiusc(titulo);
printf("%s \n", string);
printf("%s \n", string_maiusc("Matrizes e Ponteiros"));
}

6&#4c
G !  
 
Assim como pode-se criar funções que retornam ponteiros, também pode-se
criar matrizes de ponteiros. Mais comumente serão usadas matrizes para conter strings
de caracteres.
Como exemplo, a declaração a seguir cria uma matriz chamada
 que contém
ponteiros para string de caracteres:
char *dias[7]= {³Domingo´, ³Segunda´, ³Terça´, ³Quarta´, ³Quinta´,
³Sexta´, ³Sábado´};

Se for examinado o tipo da matriz da direita para a esquerda, será visto que a
matriz contém sete elementos. O asterisco antes do nome da variável especifica um
ponteiro. Se combinar o nome do tipo „ que precede o nome da variável, a
declaração se tornará uma matriz de ponteiros para strings de caractere.
6) # !


     c


G   %
    



Ao criar uma matriz de string de caracteres, a Linguagem C armazena os
ponteiros para cada string dentro dos elementos da matriz.
O programa a seguir percorre em um laço a matriz , que contém ponteiros
para strings que contém os nomes dos dias da semana, como mostrado aqui:
#include <stdio.h>

void main(void)
{
char *dias[7] = {"Domingo", "Segunda", "TerÁa",
"Quarta", "Quinta", "Sexta", "S bado"};

int i;

for (i = 0; i < 7; i++)


printf("dias[%d] contÃm %s \n", i, dias[i]);
}

6.4  !  
 
!  
 
%
  



A declaração a seguir cria um ponteiro para uma string de caracteres:
char **dia_útil_ptr;

O programa a seguir usa um ponteiro para um ponteiro para string de caracteres


para exibir o conteúdo da matriz  :
#include <stdio.h>
void main(void)
{
char *diasuteis[] = {"Segunda", "Terça", "Quarta",
"Quinta", "Sexta", "" };
char **dia_util;
dia_util = diasuteis;
while (*dia_util)
printf("%s \n", *dia_util++);
}
Quando o programa inicia, ele atribui ao ponteiro " o endereço inicial da
matriz  (o endereço da string Segunda). O programa repete então um laço até
encontrar o ponteiro para a string NULL (a condição final).
660 
    %
   !  

Muitas vezes strings de caracteres são inicializadas como segue:
char titulo[] = ³Unesp Ilha Solteira´;

Quando se declara uma matriz com colchetes vazios, o compilador C aloca


memória suficiente para armazenar os caracteres especificados (e o terminador NULL),
atribuindo à variável titulo um ponteiro para o primeiro caractere. Como o compilador C
automaticamente aloca a memória necessária e depois trabalha com um ponteiro para a
memória, os programas podem usar um ponteiro de string de caracteres, em vez de uma
matriz, como mostrado a seguir:
char *titulo = ³Unesp Ilha Solteira´;

69+!  
 5
Ao declarar uma variável ponteiro, é preciso especificar o tipo do valor para o
qual o ponteiro aponta. Quanto se faz isso, o compilador pode, mais tarde, efetuar
aritmética de ponteiros corretamente e adicionar os valores de deslocamentos corretos
quando incrementar ou decrementar o ponteiro. Em alguns casos, no entanto, os
programas não manipularão o valor de um ponteiro de qualquer maneira. Em vez disso,
os programas somente irão obter um ponteiro para uma posição de memória com a qual
o programa determinará o uso do ponteiro.
Nesses casos, os programas poderão criar um ponteiro para o tipo , como
mostrado aqui:
void *ponteiro_memoria;

6B!  
  
 A ' 
A Linguagem C permite criar ponteiros para todos os tipos de dados. Além
disso, ela permite que os programas criem e usem ponteiros para as funções. O uso mais
comum dos ponteiros para funções é permitir que os programas passem uma função
como um parâmetro para outra função. As seguintes declarações criam ponteiros para
funções:
int (*min)();
int (*max)();
float (*media)();

Observe o uso dos parênteses entre os nomes das variáveis. Se os parênteses


fossem removidos, as declarações serviriam como protótipos de função para as funções
que retornam ponteiros para um tipo específico, como mostrado aqui:
int *min();
int *max();
float *media();

Ao ler uma declaração de variável, deve-se começar com a declaração mais


interna que aparece dentro dos parênteses, e, depois, trabalha-se da direita para a
esquerda:
int (*min)();

6C!  
 
A 
O uso mais comum de um ponteiro para uma função é passar essa função como
um parâmetro para outra função. O programa a seguir passa a função
 ou
 para a
função  „  . Dependendo da função que o programa passa, o valor que
 „   retorna será diferente:
#include <stdio.h>
int pega_result(int a, int b, int (*compare)())
{
return(compare(a, b)); // Chama a função passada
}
int max(int a, int b)
{
printf("Em max \n");
return((a > b) ? a: b);
}
int min(int a, int b)
{
printf("Em min \n");
return((a < b) ? a: b);
}
void main(void)
{
int result;
result = pega_resu lt(1, 2, &max);
printf("O maximo entre 1 e 2 Ã %d \n", result);
result = pega_result(1, 2, &min);
printf("O minimo de 1 e 2 Ã %d \n", result);
}

6  4    !  


 
  !  
 
 
!  

A Linguagem C permite criar variáveis que são ponteiros para outros ponteiros.
Em geral, não há limite no número de indireções (ponteiros para ponteiros) que os
programas podem usar. No entanto, para a maioria dos programadores, usar mais do que
um ponteiro para um ponteiro resultará em confusão considerável, e tornará seus
programas muito difíceis de compreender. Por exemplo, o programa a seguir usa três
níveis de ponteiros para um valor do tipo int. Separe um tempo para experimentar este
programa e desenhe os níveis de indireção em um pedaço de papel até compreender o
processamento que ele executa:
#include <stdio.h>
int qual_e_o_valor(int ***ptr)
{
return(***ptr);
}
void main(void)
{
int *nivel_1, **nivel_2, ***nivel_3, valor = 1001;
nivel_1 = &valor;
nivel_2 = &nivel_1;
nivel_3 = &nivel_2;
printf("O valor à %d \n", qual_e_o_valor(nivel_3));
}
6%  c 
 apresentado à seguir, uma síntese do que foi tratado em cada item deste
módulo. Com esta síntese você poderá relembrar conceitos vistos durante nosso estudo
ou mesmo direcionar seu estudo, caso você já tenha conhecimentos na Linguagem C.
:Y : 6  !  
   ( 
 : é visto que um ponteiro é
uma variável ou um valor que contem um endereço.
:Y : 6  0 
    ( 
    5
$ : foi visto
como obter um endereço de uma variável e quando os programas precisarem
determinar o endereço de uma variável, deverão usar o operador de endereço da
Linguagem C ³&´.
:Y : 6   
c
G !  
 :é
mostrado o código de um programa que exibe o endereço inicial de várias matrizes
diferentes.
:Y : 6&  +

 ( 
?H@c
G:
foi visto que se o operador de endereço for aplicado a uma matriz, a Linguagem C
retornará o endereço inicial da matriz.
:Y : 6)  0 
  5
$   !  
 : foi visto que para
declarar um ponteiro, precisa-se especificar o tipo do valor ao qual o ponteiro aponta
(tal como int, float, char, etc.) e um asterisco (*) antes do nome da variável.
:Y : 6.  0
<
   !  
: foi explicado que
desreferenciar um ponteiro é o processo de acessar o valor de uma posição de memória
específica. Para desreferenciar o valor de um ponteiro, usa-se o operador asterisco de
indireção (*).
:Y : 664  5
 !  
:foi apresentado o código de
um programa em que o valor de um ponteiro é usado para receber o endereço de uma
variável de depois o ponteiro é usado para indicar o valor armazenado na posição de
memória que ele indica.
:Y : 69  !  
   !
I 
    A : foi visto que
quando for necessário alterar o valor de um parâmetro, deverá passar para a função um
ponteiro para um parâmetro. Foi apresentado um programa que usa os ponteiros para
dois parâmetros do tipo   para permutar os valores das variáveis.
:Y : 6B
J !  
 :foi explicada de manira clara
a aritmética de ponteiros, que trata os ponteiros como valores que podem ser somados
ou subtraídos.
:Y : 6C 
   0 
   !  
:foram
vistas as operações de incremento e o decremento do valor de um ponteiro, que servem
para apontar para a próxima posição ou para a posição anterior na memória.
:Y : 6!


%
   !  
: foi visto
um programa que usa uma função para exibir uma string de caracteres usando um
ponteiro.
:Y : 6  A '  8 

 !  
 : foi explicado que o
valor que uma função retorna é sempre do tipo declarado no protótipo ou cabeçalho da
função. Além de retornar esses tipos básicos, as funções podem declarar ponteiros para
os valores.
:Y : 6   
   A  8 

   !  
: foi
visto um programa que cria uma função que converte todos os caracteres de uma string
para maiúsculas e depois retorna um ponteiro para uma string.
:Y : 6&4c
G !  
 :foi explicado que assim como
pode-se criar funções que retornam ponteiros, também pode-se criar matrizes de
ponteiros. Mais comumente serão usadas matrizes para conter strings de caracteres.
:Y : 6)  !


     c


G   %
    


:foi visto um programa que percorre em um laço uma matriz ¢ que contém
ponteiros para strings que contém os nomes dos dias da semana.
:Y : 6.4  !  
 
!  
 
%
  


:foi visto um programa que usa um ponteiro para um ponteiro para string de
caracteres para exibir o conteúdo de uma matriz.
:Y : 66  0 
       %
     
!  
:foi visto como declarar uma constante string usando um ponteiro.
:Y : 69+!  
 5:foi dada uma explicação geral
sobre o ponteiro do tipo void.

:Y : 6B!  
  
 A ' :foi visto que a Linguagem C
permite que os programas criem e usem ponteiros para as funções.
:Y : 6C  !  
 
  A : foi visto que o uso mais
comum de um ponteiro para uma função é passar essa função como um parâmetro para
outra função.
:Y : 6  4    !  
 
  !  
 
 
!  
: foi visto que a Linguagem C permite criar variáveis que são ponteiros para
outros ponteiros. Em geral, não há limite no número de indireções (ponteiros para
ponteiros) que os programas podem usar.
Y

c 9#%   
8$ 
9 

Na Linguagem C, um arquivo é um conceito lógico que pode ser aplicado a
tudo, desde arquivos em disco até terminais. Um fluxo é associado a um arquivo
específico pela realização de uma operação de abertura. Uma vez que um arquivo esteja
aberto, informações podem ser intercambiadas entre o arquivo e o seu programa.
Nem todos os arquivos têm as mesmas capacidades. Por exemplo, um arquivo
em disco pode suportar acesso randômico enquanto um acionador de fita não pode. Isso
ilustra um ponto importante sobre o sistema de E/S da linguagem C: todos os fluxos são
os mesmos, mas nem todos os arquivos os são.
Se pode suportar acesso randômico, então uma abertura de um arquivo também
inicializa um  „Y  Y *+Y Y „ Y no começo do arquivo. À medida que
cada caractere é lido ou escrito para o arquivo, o indicador de posição é incrementado,
assegurando, assim, a progressão através do arquivo.
Um arquivo é desassociado de um fluxo específico por meio de uma operação de
fechamento. Em fluxos abertos para saída, o fechamento do fluxo faz com que o
conteúdo, se houver, da área intermediária (buffer) seja descarregado para o dispositivo
externo. Esse processo é geralmente referenciado como uma 
 -(  „Y de
apontador e garante que nenhuma informação será acidentalmente esquecida na área
intermediária do disco. Todos os arquivos são fechados automaticamente quando o
programa termina normalmente.

9+!  
 
8$
A linha comum que une o sistema de E/S de disco aos programas escritos em C
é o  „Y  Y „ . Um ponteiro de arquivo é um ponteiro para uma área na
memória (buffer) onde estão contidos vários dados sobre o arquivo a ler ou escrever,
tais como o nome do arquivo, estado e posição corrente. O rr „Y apontado pelo
ponteiro de arquivo é a área intermediária entre o arquivo no disco e o programa.
Este buffer intermediário entre arquivo e programa é chamado ³fluxo´, e no
jargão dos programadores é comum falar em funções que operam fluxos em vez de
arquivos. Isto se deve ao fato de que um fluxo é uma entidade lógica genérica, que pode
estar associada a uma unidade de fita magnética, um disco, uma porta serial, etc.
Adotaremos esta nomenclatura aqui.
Um ponteiro de arquivo é uma variável ponteiro do tipo /012Yque é definida em
O. Para ler ou escrever em um arquivo de disco, o programa deve declarar uma (ou
mais de uma se formos trabalhar com mais de um arquivo simultaneamente) variável
ponteiro de arquivo. Para obter uma variável ponteiro de arquivo, usa-se uma declaração
semelhante a esta:
FILE *fp;

onde rYé o nome que escolhemos para a variável (podia ser qualquer outro).
9 "
 
8$4  A+!(>
Muitos programas em Linguagem C armazenam e lêem informações de um
arquivo. Antes que os programas possam ler ou gravar informações em um arquivo, será
preciso abrir o arquivo. A função r  permite que seus programas abram um arquivo.
O formato de r  é como segue:
#include <stdio.h>
FILE *fopen(const char *nomearq, const char *modo);

O parâmetro 
„Yé uma string de caracteres que contém o nome do arquivo
desejado, tal como "c:\arqdados.dat". O parâmetro modo especifica como quer-se usar o
arquivo - para ler, gravar ou anexar. A tabela abaixo descreve os valores de modo que
fopen suporta:
c % <
"r" Abre um arquivo para leitura
"w" Cria um arquivo para escrita
"a" Acrescenta dados para um arquivo existente
"rb" Abre um arquivo binário para leitura
"wb" Cria um arquivo binário para escrita
"ab" Acrescenta dados a um arquivo binário existente
"r+" Abre um arquivo para leitura/escrita
"w+" Cria um arquivo para leitura/escrita
"a+" Acrescenta dados ou cria um arquivo para leitura/escrita
"r+b" Abre um arquivo binário para leitura/escrita
"w+b" Cria um arquivo binário para leitura/escrita
"a+b" Acrescenta ou cria um arquivo binário para leitura/escrita
"rt" Abre um arquivo texto para leitura
"wt" Cria um arquivo texto para escrita
"at" Acrescenta dados a um arquivo texto
"r+t" Abre um arquivo-texto para leitura/escrita
"w+t" Cria um arquivo texto para leitura/escrita
"a+t" Acrescenta dados ou cria um arquivo texto para leitura/escrita
 A função fopen retorna um ponteiro (chamado ponteiro de arquivo) para uma
estrutura do tipo FILE que o arquivo de cabeçalho stdio.h define. Seus programas
usarão o ponteiro de arquivo para suas operações de entrada e saída. Se a função fopen
não puder abrir o arquivo especificado, ela retornará o valor NULL. Seus programas
sempre devem testar o valor de retorno de fopen para garantir que abriu o arquivo com
sucesso, como mostrado aqui:
if ((pa = fopen("NOMEARQ.EXT", "r")) != NULL)
{
/*Arquivo aberto com sucesso*/
}
else
{
/*Erro ao abrir o arquivo*/
}

Dentro do programa, é preciso declarar a variável ponteiro de arquivo como


segue:
void main()
{
FILE *pa /*Ponteiro para uma est rutura do tipo FILE*/

Y Muitos programas abrem um arquivo para entrada e outro para saída. Em tais
casos, você poderia declarar dois ponteiros de arquivo, como mostrado aqui:Y
FILE *entrada, *saida;

9&( 

A(
 Como você aprendeu, quando os programas efetuam operações de entrada e
saída, elas normalmente declaram ponteiros de arquivos usando a estrutura FILE, como
visto no final do item 3.3.
Se você examinar o arquivo de cabeçalho O, encontrará a definição da
estrutura FILE. Esta definição foi tomada do Turbo C++ Lite:
typedef struct
{
short level; /*Nivel do buffer cheio/vazio*/
unsigned flags; /* Sinalizadores de status*/
char fd; /* Descritor de arquivo*/
unsigned char hold; /*Caracter ungetc se não existir um
buffer*/
short bsize; /*Tamanho do buffer*/
unsigned char *buffer; /*Buffer de transferência*/
unsigned char *curp; /*Ponteiro ativo atual*/
unsigned stemp; /*Indicador de arquivo temporário*/
short token; /*Usado para verificação de validade*/
} FILE /*Esse é o objeto FILE */

Y A estrutura FILE contém o descritor de arquivo de baixo nível que o sistema


operacional usa para acessar o arquivo, o tamanho do buffer do arquivo e a localização,
o buffer de caracteres que unget usa, um sinalizador que indica se o arquivo é um
arquivo temporário, e outras variáveis sinalizadoras. Além disso, a estrutura FILE
armazena o ponteiro de arquivo que controla sua localização atual dentro do arquivo.
Se estiver trabalhando no ambiente do DOS, a maioria dos compiladores definirá
uma matriz de tamanho fixo (normalmente 20) dos ponteiros de arquivo que contém as
informações para cada arquivo que seu programa abrirá. Se o programa precisa abrir
mais de 20 arquivos, consulte a documentação do compilador para conhecer os passos
que precisará seguir para modificar o tamanho da matriz de ponteiros de arquivo.
9)A 2 
8$"

 Fechar um arquivo instrui o sistema operacional a esvaziar todos os buffers de
disco associados com o arquivo e a liberar os recursos do sistema que o arquivo
consumiu, tais como os dados de ponteiros de arquivo. A função r  fecha o arquivo
associado com o ponteiro de arquivo especificado, como mostrado aqui:
#include <stdio.h>
int fclose (FILE *pont_arquivo);

Se r  for bem sucedida, retornará o valor 0. Se ocorrer um erro, r 


retornará a constante EOF, como mostrado aqui:
if (fclose(pa) == EOF)
printf ("Erro ao fechar o arquivo de dados \n");

À medida que for examinando programas em Linguagem C, será visto que a


maioria deles não testa o valor de retorno de r , como mostrado aqui:
fclose(pa);

Na maioria das vezes, se uma operação fechar arquivo apresentar erro, o


programa poderá fazer muito pouco para corrigir a situação. No entanto, se estiver
trabalhando com arquivos de dados críticos, deverá exibir uma mensagem de erro para o
usuário para que ele possa examinar o conteúdo do arquivo.
Se não chamar a função fclose, C fechará os arquivos abertos quando o
programa terminar.

9.     =
$   <
'   
8$ 


 5 G
 Quando os programas efetuam operações de entrada e saída em arquivos, podem
ler e gravar dados um caracter de cada vez ou uma linha de cada vez. Para as operações
de entrada e saída de caractere, os programas podem usar as funções r  e r , cujos
formatos são mostrados aqui:
#include <stdio.h>
int fgetc (FILE *pont_entrada);
int fputc (int caractere, FILE *pont_saida);

A função fgetc lê o caracter atual do arquivo de entrada especificado. Se o


ponteiro de arquivo tiver chegado ao final do arquivo, fgetc retornará a constante EOF.
A função fputc gravará um caractere na posição do ponteiro de arquivo atual dentro do
arquivo de saída especificado. Se um erro ocorrer, fputc retornará a constante EOF. O
programa a seguir, usa fgetc e fputc para copiar o conteúdo do arquivo do diretório raiz
config.sys para um arquivo chamado config.tst:
#include <stdio.h>

void main(void)
{
FILE *entrada, *saida;
int letra;

if ((entrada = fopen(" \\CONFIG.SYS", "r"))==NULL)


printf("Erro ao abrir \\CONFIG.SYS \n");
else if ((saida = fopen(" \\CONFIG.TST", "w"))==NULL)
printf("Erro ao abrir \\CONFIG.TST \n");
else
{
/* Lê e grava cada caractere no arquivo*/
while ((letra = fgetc(entrada)) != EOF)
fputc(letra, saida);
fclose(entrada); /* Fecha o arquivo entrada */
fclose(saida); /* Fecha o arquivo saida */
}
}

96+!  
 ! !  
 
8$
 O item 8.4 apresentou a estrutura FILE. Como foi visto, um dos campos da
estrutura armazena um ponteiro da posição para localização atual dentro do arquivo.
Quando abre-se um arquivo para operações de leitura ou gravação, o sistema
operacional define o ponteiro da posição no início do arquivo. Toda vez que ler ou
gravar um caractere, o ponteiro da posição avançará um caractere. Se ler uma linha de
texto do arquivo, o ponteiro da posição avançará para o início da próxima linha. Usando
o ponteiro da posição, a funções de entrada e saída de arquivo sempre podem controlar a
localização atual dentro do arquivo. Quando abre-se um arquivo no modo de anexação,
o sistema operacional define o ponteiro da posição no final do arquivo. A tabela a seguir
especifica a localização na qual r  coloca o ponteiro da posição quando abre-se o
arquivo nos modos de leitura, gravação e anexação.
c "

 ! !  

8$
a Imediatamente após o último caractere do arquivo
r No início do arquivo
w No final do arquivo

990 
  !  
8$
 No item anterior foi visto como a Linguagem C controla a posição atual em
arquivos abertos para as operações de entrada e saída. Dependendo do programa,
algumas vezes será necessário determinar o valor do ponteiro de posição.
Em tais casos usa-se a função r , como segue:
#include <stdio.h>
long int ftell (FILE *pont_arquivo);

A função r retorna um valor inteiro longo que especifica o byte de


deslocamento à partir da posição atual no arquivo especificado. O programa a seguir usa
r para exibir informações do ponteiro de posição. O programa começa abrindo o
arquivo do diretório raiz config.sys no modo de leitura. O programa então usa r para
exibir a posição atual. Em seguida, o programa lê e exibe o conteúdo do arquivo. A pós
encontrar o final do arquivo, o programa novamente usará r para exibir a posição
atual, como segue:
#include <stdio.h>

void main(void)
{
FILE *entrada;
int letra;

if ((entrada = fopen(" \\CONFIG.SYS", "r")) == NULL)


printf("Erro ao abrir \\CONFIG.SYS \n");
else
{
printf("A posição atual é o byte %d \n\n",
ftell(entrada));
/* Lê e grava cada caractere no arquivo*/
while ((letra = fgetc(entrada)) != EOF)
fputc(letra, stdout);
printf("\nA posição atual é o byte %d \n",
ftell(entrada));
fclose(entrada); /* Fecha o arquivo entrada */
}
}
<p class=MsoNormal styl
Y

c  
      
9 2 = 
No modo gráfico, a tela do monitor de vídeo é dividida numa fina malha de
pontos individuais, chamados de elementos de imagem, ou pixel. Qualquer pixel pode
ser apagado ou iluminado, o que vem a ser o princípio básico para a criação de imagens
gráficas. A resolução da tela é descrita em termos do número de pixeis por linha ou por
coluna. Uma tela VGA (Adaptador Gráfico Colorido) tem 640 linhas por 480 colunas,
como está mostrado na Figura (a).  importante notar que o sistema de numeração inicia
no canto superior esquerdo da tela no ponto (x,y) = (0,0).
?C¢C@  K K ?C¢&6B
@

 K L

?. B¢C@ ?. B¢&6B@
?@ ?@
&)Yï YY 
 YYY5TVY
&)Yï YY 
YYY 
Y
Segundo as figuras (a) e (b) acima, vemos que o eixo y na tela do PC está
invertido em relação ao eixo yc do plano cartesiano. Por isto, para mostrar na tela do PC
no gráfico como se fosse no plano cartesiano deve-se fazer a seguinte equivalência:

Y Y yv = ymax/2 - yc

Y %YYYYYMYYYYYY,
Y Y Y YMYYYYY 
 Y
Y Y YYMY!YYY YY,Y
Então a tela do vídeo terá o sistema de eixos conforme dado na figura
abaixo:
?C¢ C@

3

?&6B¢C@

?C¢C@ 

?C¢# B@

(c)Eixos cartesianos no monitor CGA


BY Y0    
=
<
 Provavelmente em seu programa seja necessário detectar qual o adaptar gráfico
está em uso. Para isso usamos a função  „. Esta função detecta qual adaptador
(CGA, VGA, EGA, Hercules etc.) está conectado e informa o modo de resolução mais
alto do driver daquele adaptador. A sintaxe da função é:
detectgraph(&gdriver,&gmode);

Os valores que os parâmetros gdriver e gmode poderão assumir são:


=   =  =  >? & $  

:Y$YTVY TVBYTV:YTV/Y BY:Y/Y.Y>Y ./B/BBY./B/BBY./B/BBY


TV.YTV0Y ./B/BBYA>B/BBY$Y/Y 
Y

/Y$YNTVY NTVBYNTV:Y BY:Y/Y.Y>Y?Y ./B/BBY./B/BBY./B/BBY


NTV/YNTV.Y ./B/BBYA>B/BBY$Y/Y 
Y
NTVNïQYNTV0YY A>B>;BY$Y/Y 
Y

.Y$YïTVY ïTV'YïTV0Y BY:Y A>B/BBY$Y:AY 


YA>B.?BY$Y:AY

Y

>Y$YïTVA>Y ïTVA>'YïTVA>0Y BY:Y A>B/BBY$Y:AY 


YA>B.?BY$YY>Y

Y

?Y$YïTV$N'-'Y ïTVN'-'0Y .Y A>B.?BY$Y/Y 


Y

AY$Y0IN;?:>Y 0IN;?:>0Y0IN;?:>'Y BY:Y A>B>;BY$Y/?AY 


Y:B/><A;Y$Y
/?AY 
Y

<Y$YïG6ï Y ïGN'-'0Y BY </BU.>;Y$Y/Y 


Y

;Y$YVHH>BBY VHH>BBBYVHH>BB:Y BY:Y/Y.Y>Y?Y ./B/BBY./B/BBY./B/BBY


VHH>BB/YVHH>BB.Y ./B/BBYA>B/BBY$Y/Y 
Y
VHH>BBNïQYVHH>BB0Y A>B>BBY$Y/Y 
Y

@Y$Y5TVY 5TV'Y5TVNïQY5TV0Y BY:Y/Y A>B/BBY$Y:AY 


YA>B.?BY$Y:AY

YA>B>;BY$Y:AY 
Y

:BY$Y4./<BY 4./<B0Y BY </B.?BY$Y/Y 


Y

A seguir temos um exemplo de um programa que detecta o adaptador


imformando o mesmo:

#include <stdio.h>

#include <graphics.h>

main()

{
int adaptador_grafico,i,j;

int modo_grafico;

clrscr();

detectgraph(&adaptador_grafico,&modo_grafico);

printf("\n O adaptador detectado é %d ",adaptador_grafico);

printf("\n O modo de alta resolucao %d",modo_grafico);

getch();

No programa anterior, por exemplo, se o monitor de vídeo for CGA aparecerá:


 '      

 

     

Y 0 Y YY


YY@Y&5TV)YY Y  YYY #Y YYY/Y&A>BY
 YY>;BY   )!Y

B  Y G !


 =
<
 " Y Y

 Y Y 2Y

Y 
Y Y

 Y
  YY  YY
 2Y
YY


YY  Y
Y !YVY #YOO!"Y YY  Y
YY Y
Y Y Y
 Y   Y Y  #Y !"Y 
Y Y Y Y Y Y Y
 $YYY
 !YVY # !"Y  YYY
 Y  Y
Y

&)Y 
Y Y 
Y Y 
Y
  !Y VY  
Y Y Y  Y  
Y Y
YYY Y  Y  Y  OO!"YY !"ë
#include <stdio.h>

#include <graphics.h>

main()

int adaptador_grafico;

int modo_grafico;

detectgraph(&adaptador_grafico,&modo_grafico);

initgraph(&adaptador_grafico,&modo_grafico,"c: \\tc");

getch();

closegraph();

}
O programa anterior detecta a resolução gráfica da tela, inicia a tela no modo
gráfico e depois sai do modo gráfico.
B&Y Y+"  0 ' 7 
 H
Y Y  Y
  Y  Y

 Y
  
#Y  
Y Y  Y
YY
 Y Y Y Y  Y
 Y Y  Y
  Y 


#YY

 !Y
V Y   Y  !"Y Y  #!"Y

Y Y 
 Y 
 Y  Y 
 Y  Y  Y

 YYYYY!YY  Y  Y
$ Y Y  Y YYY
Y  Y Y 

Y  Y Y Y 
Y Y Y Y Y TVY 5TVY ïTVY  !Y VY
 
YY

Y 
YY Y  Y  Y  Y
  %
YY

YY

YY

#include <stdio.h>

#include <graphics.h>

main()

int adapt, mod, xmax, ymax;

detectgraph(&adapt,&mod);

initgraph(&adapt,& mod,"c:\\tc");

xmax=getmaxx();

ymax=getmaxy();

outtextxy(100,100,´Estamos no modo gráfico! Aperte uma


tecla.´);

getch();

closegraph();

printf("\n O eixo x da tela vai de 0 a %d", xmax);

printf("\n O eixo y da tela va i de 0 a %d", ymax);

getch();

Este programa informa quais são as dimensões máximas x e y da tela gráfica. Se


a tela em questão for VGA o resultado será:
 '   
  

 '   


 
B)Y Y0 2 -  7 
 N  Y #Y Y  Y
  YY YY  
Y 
$ Y Y
YYY

Y 

Y  Y  Y 
Y  
 Y   Y   ,  !Y 4
Y  Y 
 Y Y   Y Y
YY #YO!"Y YYY  Y %

line(xi,yi,xf,yf);

Y ' Y 
=
 Y 
Y 
2  Y  Y 
Y Y  Y 

Y  Y Y  Y Y
Y YYYYYY!Y
Y VY  
YY YY #YO!"¢Y Y Y

Y%Y
#include <graphics.h>

main()

int adapt, mod ;

detectgraph(&adapt,& mod);

initgraph(&adapt,&mod,"c: \\tc");

line(0, 0, getmaxx(), getmaxy());

getch();

closegraph();

B. Y0 2 - I  7 


 N  Y #Y  Y   Y
  Y Y  Y Y   
Y  
$ Y Y
= Y Y
!Y4
Y Y
 YY  YYYY #Y!"Y YYY  Y %

rectangle(xsup, ysup, xinf, yinf);

Y ' Y 
=
 Y 
Y 
2  Y  Y 
YY  Y 

Y  Y Y  Y Y

= Y Y Y Y Y Y 



Y   
Y Y Y & Y  )Y Y Y Y 

Y

YYY&Y)!Y
Y VY  
Y 
 YY YY #Y!"¢Y Y Y

Y%Y
#include <graphics.h>

main()

int adapt, mod ;

detectgraph(&adapt,&mod);

initgraph(&adapt,&mod,"c: \\tc");
rectangle(5, 10, 300, 100);

getch();

closegraph();

B60 2 !  7 


 Muitas são as aplicações gráficas em que é necessário desenhar-se um ponto na
tela, ou seja, ela acende um único pixel na tela. Para este propósito, a Linguagem C tem
a função   que tem a seguinte sintaxe:
putpixel(x, y, cor);

Y ' Y 
=
 Y 
Y 
2  Y  Y 
Y Y  Y 

Y  Y Y 
Y Y
Y&)YYY&Y) YY 
Y   Y
Y2 
Y VY  
Y 
 YY YY #Y
O !"¢Y Y Y

Y%Y
#include <graphics.h>

main()

int adapt, mod ;

detectgraph(&adapt,&mod);

initgraph(&adapt,&mod,"c: \\tc");

putpixel(50,100,15);

outtextxy(55,110," aqui 1" );

putpixel(300,100,15); outtextxy(303, 102," aqui 2");

getch();

closegraph();

B9Y Y0 2 
 7 
 N  Y #Y Y  Y
  YY YY  
Y 
$ Y Y ,
YY!Y

Y Y
 YY  YYYY #YO!"Y YYY  Y %

circle(xcentro, ycentro, raio);

' Y 
=
 Y 
Y 
2  Y  Y 
Y Y  Y 

Y  Y Y  Y Y
,
YPY

Y Y 
 Y& 
Y 
)Y
YOY
VY  
Y 
 YY YY #YO!"¢Y Y Y

Y%Y
#include <graphics.h>

main()

int adapt, mod ;

detectgraph(&adapt,&mod);

initgraph(&adapt,&mod,"c: \\tc");

circle(300,100,50);

getch();

closegraph();

O exemplo a seguir é um programa que desenha uma reta, um retângulo, um


círculo e dois pontos:
#include <graphics.h>

main()

int adapt, mod ;

detectgraph(&adapt,&mod);

initgraph(&adapt,&mod,"c: \\tc");

line(5, 10, 300, 100);

rectangle(5, 10, 300, 100);

putpixel(100, 50, 1);

putpixel(200, 50, 1);

circle(300, 100, 50);

getch();

closegraph();

BBY Y0 2 


 7 
 N  Y #Y Y  Y
  YY YY  
Y 
$ Y Y
Y ,

YY
!Y4
Y Y
 YY  YYYY #Y!"Y YYY  Y %
arc(xcentro, ycentro, angulo_inicial, angulo_final, raio);

Y 'Y 
YYY Y 
 Y! #"YYY
Y
YO!' Y
=
 Y

OOOYY
OY   Y Y=  Y YYYY
 YYYBY YY
 #Y
YY
YY
YY@BYY #Y
 YY
Y !Y
VY  
Y 
 YY YY #Y!"¢Y Y Y

Y%Y
#include <graphics.h>

main()

int adapt, mod ;

detectgraph(&adapt,&mod);

initgraph(&adapt,&mod,"c: \\tc");

arc(300, 100, 0, 90, 100);

getch();

closegraph();

BC  7 =


<
ïY   Y    Y  Y 

 Y 
#Y  
Y 
 Y 
 Y 
  Y Y  Y Y
 Y 
Y  
Y $ !Y4
Y Y
 YY  YYYY #Y O!"Y Y
Y Y Y Y  Y Y 
Y 
Y
 YY

YY%
#include <graphics.h>

main()

int adapt, mod,i ;

detectgraph(&adapt,&mod);

initgraph(&adapt,&mod,"c: \\tc");

for (i=0; i<200;i++)

line(i+5,i+10,i+300,i+100);

rectangle(i+5, i+10,i+300,i+ 100);

putpixel(100, 50, 15);

putpixel(200, 50, 15);


circle(300+i, 100+i, 50+i);

delay(1000);

cleardevice();

getch();

closegraph();

B Yc  


0 2
ïY   Y   Y 
Y  
Y

YY 
Y Y Y YY Y   Y
 Y #Y  Y  Y  Y 

 !Y 4
Y  Y 
 Y Y   Y Y Y Y  #Y
!"Y YYY  Y %

setcolor(cor);

' Y
 Y Y YY
 
YY
=
YY
YYY5TVY #Y YY  
%Y
2%
 %
 2%


4GïH'Y BY V(6Y :Y

5ïGQïY /Y 0V-'Y .Y

5ïGNï'Y >Y NVTï-HVY ?Y

NVGG'NY AY 0-(VYVG'Y <Y

0-(VYï 6G'Y ;Y V(6YVG'Y @Y

5ïGQïYVG'Y :BY 0V-'YVG'Y ::Y

5ïGNï'YVG'Y :/Y NVTï-HVYVG'Y :.Y

VNVGï'Y :>Y IGV-'Y :?Y

BY Y c   


   A    !
2   
0 2
ïY  Y   Y 
Y  
Y

YY 
YY YYY
#YY
 Y
 Y  Y Y #Y Y Y  Y

 !Y4
Y Y
 YY  YYYY
 #Y O #!"YY O!" YYY  Y %

setfillstyle(padrao,cor);

floodfill(x, y, borda);
YVY #Y O! # "
 Y Y
Y YY
 YY

YYY
Y 
Y &Y )Y Y Y 
Y Y Y 
#Y   Y Y 
 Y  Y Y  
#Y
 &)YY 

YY 
Y   Y
Y !Y

VY #Y O #!"Y YY


#YYY 
YY
 Y
 Y  Y Y
 YY
=
Y Y Y Y Y
 Y%Y

>6    >6   

( 
YY Y  
Y Y

È  Y
 Y   Y  Y YKKKY

  Y  Y


  YKKKY !  Y  Y YFFFY

0  Y  Y


  YYFFFY 7
 Y Y
 Y

8
 Y
  Y
 Y 9  Y
 Y

(  Y 
 Y   Y  Y

VY  
Y  
 Y Y Y  Y   Y O #!"Y Y  O!"Y Y Y 

Y
%Y
YY
#include < graphics.h>

main()

int adapt, mod, xm,ym ;

detectgraph(&adapt,&mod);

initgraph(&adapt,&mod,"c: \\tc");

xm = getmaxx()/2;

ym = getmaxy()/2;

setcolor(LIGHTGREEN);

circle(xm,ym,100);

circle(xm,ym,150);

circle(xm,ym,250);

setfillstyle(2,1);

floodfill(xm,ym+10,10);

setfillstyle(7,1);
floodfill(xm,ym+160,10);

setfillstyle(3,1);

floodfill(xm,ym+260,10);

setfillstyle(7,1);

floodfill(xm*2,ym*2,10);

getch();

closegraph();

9 )@ "  - 


Y VY
 YPY  
Y Y , YY YY
YY YY Y  !Y
Y  Y , Y  2Y 
Y


Y   Y   Y 
Y  Y   Y  Y  Y

 
Y  Y  Y  Y 2Y YY   YY  Y!Y
:Y:YY 9 2 = ëYYY Y #YYY Y  YY
Y
 YY  Y!Y
:Y:YY 9 È   " "   2 "  = ë  Y Y Y Y  #Y
 
Y Y YY
Y
 YY !Y
:Y:YY 9   / A   "  = ëY  Y Y  Y  Y Y  #Y

&)Y  Y Y  Y 
Y Y  Y Y Y Y
 Y   Y Y  #Y
 
&)Y
YYYYYYY  $YYY
 !
:Y:YY9 %1"   4   ë Y Y Y Y  Y &)Y
Y &)Y 
$ Y  Y   Y  Y Y Y  $ Y  Y   Y Y
!
:Y:YY9 ! & 
"  ë Y 
YY #Y&)Y Y Y
Y
YY!Y
:Y:YY9 0 & 
"5   돏Y 
YY #Y
  &)Y Y
 Y Y
= YY!Y
:Y:YY 9 7   &    "   ë Y 
Y Y  #Y  &)Y  Y
 Y YYY!Y
:Y:YY 9 8   &   @   ë Y 
Y Y  #Y 
&)Y  Y
 Y YYY!Y
:Y:YY 9 9  &  2   돏Y 
YY #Y
&)Y Y
 Y Y
Y 

YY!Y
:Y:YY9 (  = 돏Y 
YY #Y 
 &)Y YYY
!Y
:Y:YY9       &돏Y 
YY #Y  
&)Y Y
 Y Y 
 YY !Y
:Y:YY 9 È    3   & "   &돏Y

Y Y  Y  &)YY&) Y Y Y 
 YY YYY
 YY
Y !Y
Y

c C7   0 
A Linguagem C permite criar diversos tipos diferentes de dados particulares.
Podemos citar a „„, a +, o Y 
„ e o )  <. A „  „ é um
agrupamento de variáveis sobre um nome, que algumas vezes é chamado de
  „
 ou „ 
 de tipos de dados. A  habilita um mesmo pedaço de
memória a ser definido como dois ou mais tipos de dados diferentes. O   „

é uma lista de símbolos. O 
cria um novo nome para um tipo existente.

C( 

 
Na Linguagem C, uma „„é uma coleção de variáveis referenciadas sobre
um nome, provendo um meio conveniente de manter informações relacionadas juntas.
Uma  „*+Y Y „„forma uma fonte que pode ser usada para criar variáveis
de estruturas. As variáveis que compreendem a estrutura são chamadas de 
 .
Em geral, todos os campos na estrutura estarão logicamente relacionados uns aos
outros. Por exemplo, a informação sobre o nome e o endereço em uma lista de
endereços deve ser normalmente representada em uma estrutura.
O seguinte fragmento de código declara uma estrutura-fonte que define os
campos nome e endereço de tal estrutura. A palavra reservada „ diz ao compilador
que uma estrutura está sendo definida:
 
 Y  Y
Y Y
Y
Y
Y  Y
Y  Y

  Y Y YY



Observa-se que a declaração termina com um ponto-e-vírgula.  por isso que
uma estrutura é uma declaração. Temos ainda que, a etiqueta  „ *¢identifica essa
estrutura de dados particular e é o seu especificador de tipo.
Neste ponto do código, nenhuma variável foi declarada. Somente a forma dos
dados foi definida. Para declarar uma variável com essa estrutura, deve-se escrever:
 
 Y Y  

Esta expressão declarará uma variável estrutura do tipo  „ * chamada


r„. Quando declara-se uma estrutura, define-se um tipo de variável complexa
composto por campos. Até que se declare uma variável desse tipo, ela não existe.
Pode-se também declarar uma ou mais variáveis enquanto declara uma estrutura.
Veja a seguir um exemplo:
 
 Y  Y
Y Y
Y
Y
Y  Y
Y  Y

  Y Y YY


Y  Y Y 
Isso definirá um tipo de estrutura chamada  „ * e declarará as variáveis
r
¢rYe rcomo desse tipo.
C- <
    ( 


Campos da estrutura são referenciados pelo uso do operador de seleção de
campo: o . Por exemplo, o seguinte código atribuirá o cep 12345777 ao campo
Yda variável estrutura r„declarada anteriormente:
   Y!Y"#$$$

O nome da variável estrutura seguido por um ponto e o nome do campo


referenciarão um campo individual da estrutura. Todos os campos da estrutura são
acessados da mesma maneira. A forma geral é:
 %&% 

  

Portanto, para imprimir o cep na tela, pode-se escrever:


 Y'()
*Y   +

Isso imprimirá o cep contido no campo Yda variável estrutura r„.


Da mesma maneira, a matriz de caracteres r„O
 pode ser usada em
uma chamada à função  Y# como mostrada aqui:Y
 Y'   +

Isso passará um ponteiro para caractere para o começo do campo 


. Se fosse
necessário acessar os elementos individuais de r„O
, poderia indexar 
.
Por exemplo, pode-se imprimir o conteúdo da r„O
, um caractere por vez,
usando este código:
 Y Y
Y' Y!YY    Y,, +Y
Y'    +

Cc
G  ( 

 
O uso de
„- Y  Y „„ é o mais comum das estruturas. Para
declarar uma matriz de estruturas, deve-se primeiro definir uma estrutura e, então,
declarar uma variável matriz daquele tipo. Por exemplo, para declarar uma matriz
de 100 elementos de estrutura do tipo  „ * (definida anteriormente), deve-se
escrever:
 
 Y Y  "

Isso cria 100 conjuntos de variáveis que são organizados como definido na
estrutura  „ *. Para acessar uma estrutura específica, o nome da estrutura é
indexado.
Por exemplo, para imprimir o código cep na estrutura 3, deve-se escrever:
 Y'()
*Y   +
Como todas as variáveis matrizes, as matrizes de estruturas começam sua
indexação em zero.
C 
" ( 

 
Se duas variáveis são do mesmo tipo, pode-se atribuir uma a outra. Nesse caso,
todos os elementos da estrutura no lado esquerdo da atribuição receberão os valores
dos elementos correspondentes da estrutura do lado direito.
Por exemplo, este programa atribui o valor da estrutura 
Y para a estrutura
e exibe o resultado 10 98.6.
8 
Y-  .Y
% Y '+Y
YY Y
 
 Y/Y
Y
 YY

Y Y
Y
Y Y

 Y!Y"Y

 Y!Y01 2Y
Y!Y
Y34 
Y
Y 

YY
43Y
 Y'() Y)*Y  Y  +Y
YY

C&!  ( 

  
A ' 
Até aqui, todas as estruturas e matrizes de estruturas dos exemplos são
assumidas cY
Y

c 
      ! 
"# $ 
 / " 
Y V Y  YY
K ,Y&0K'Y9Y K  )YY  YY #Y Y  Y
 Y 
 Y YY"YY  YV !Yï Y
Y  Y
YY

YY

  
YY
Y Y
 YYYY

#Y Y   YY0K'YY

Y   Y Y  Y   Y  Y 
Y 
Y  Y 
Y Y
 Y
Y Y Y  Y  !Y
Y 'Y Y Y 
 Y Y 0K'Y Y 4Y 
#Y 
 Y Y Y Y  
Y Y

Y Y
 Y//BYY//CYY.BBYY.BC!Y4
YYYY Y Y#YY

YYY
 Y Y  YY
Y YY  #YY  YY 
Y
  Y  Y
 Y Y
 YY  
Y Y Y 
 Y   YY0K'!YVY Y
Y 
Y  
Y Y à Y  Y 

Y Y  #Y Y 


Y 
Y 
Y  Y
  Y
 YY  Y YY  
Y  !Y-Y  YY  YY  #YY
 Y Y  Y   YY 
Y 
 Y YY 
Y   Y YY  
Y
 !YHY  Y  YYY 
Y  Y YY Y  
YY  
!Y
Y
1   :    /B% 

 È2 3 4  "1 ""


V Y  Y
&)YY 

&)Y
Y  Y
YY
 YY   YY
0K'Y Y ;Y  Y :AY  !Y 'Y 
 Y °  Y   Y   Y Y  !!Y  Y 
 Y #Y

  YY  
%Y

 " "C ""D EF


Y Y
Y
YY:AY YY
Y"D    +Y

 " "1C ""D EF


Y Y
Y
YY;Y YY
Y"D    +Y

 ""C ""D G " E


ïYY 3YY
Y GY:AY Y
YY
Y"D Y   +Y

 ""1C ""D G  & E


ïYY 3YY
Y GY;Y Y
YY
Y"D Y   +Y

   2;  )  2 - 


VY  Y Y   #Y Y  Y 0'$QV $V'$B;Y Y Y  Y Y Y Y 
Y

Y0 VY Y Y   Y 


 
,   %Y

: "   - %Y;Y  Y


  Y  Y:/Y YY
  #YYY

 Y   YYY 
#YY/?Y
   +Y

)@  -%Y Y  YY:/Y Y YYY #YY ,Y  Y
Y


#+Y

VYYY
Y Y YY 
YY  
%Y

1  È1  :   " /%<2)(8<2%#

VY YY Y


$ Y Y
YYY YY 
#!Y' Y
 Y

Y  Y #Y//BY Y.BBYY !Y

  <   2B

VY 
#YVKQYY Y Y Y
YY
Y.2):Y
Y
#YY
;Y Y Y
YY
Y&.2):H)Y
Y
#YY:/Y !Y

'Y Y Y 


#Y Y Y 
 Y Y
Y Y Y  Y   Y Y

Y&IV ï„/)Y YY
Y YY 
#Y
Y 
Y  %Y

:  .2):HÈ< "

<Y AY ?Y >Y .Y /Y :Y BY

:% / /È / /


I JKÈ JK JK(

'Y
 Y Y Y 
#Y Y #Y 
Y Y  Y
 Y IV ïY Y IV ï„:Y
YY  Y 
#%Y

:  .2):< "
<Y AY ?Y >Y .Y /Y :Y BY

29 2( 2 2ÈC).E ( ( ( (

:  .2):H< "

<Y AY ?Y >Y .Y /Y :Y BY

2C).E 2È 2 2 2! 20 27 28

Y Y ' 
$ Y  Y  Y Y  IY Y Y Y Y
Y &IV ï)Y Y  Y >Y  Y  Y
   !Y-Y
Y&IV ï„:)Y #Y Y;Y Y Y    !Y4
Y
#Y Y:/Y
 Y Y 
Y

Y Y 
Y  Y
   Y 
 Y
 
Y Y Y  Y
  Y>Y   YY
YY 
Y YYY 

Y
 Y>Y   YY  
!Y

Y Y 'Y  Y 
 Y Y 

Y Y   Y Y
Y Y 
#Y Y Y 
Y
  YY YY:/Y Y Y
YY
#Y Y !Y
outportb(BASE+1,0); /* Partida no c onversor A/D, 12 bits */

a=0x80;

while(a==0x80)

a=inportb(BASE+2)&0x80; /*espera por EOC = 0, fim conversão */

BS=(inportb(BASE)&0xF0)>>4; /* leitura Byte inferior e correção */

Bi=inportb(BASE+1); /* leitura byte superior */

vec = 16 * BS + Bi ; /* rearranjo valor digital em 12 bits */

  È<   B2

Y Y VY 
#Y Y
Y 
Y Y Y 
Y  Y Y :/Y  Y 
Y  Y

   Y
 YY  Y
Y&YQKVYB)%Y

:  .2):H8<: "

<Y AY ?Y >Y .Y /Y :Y BY

27 20 2! 2 2 2È 2 2(C)1E

:  .2):H9<: "

<Y AY ?Y >Y .Y /Y :Y BY

K K K K 2C)1E ßY
 MN -
Y Y Y
 Y