Você está na página 1de 139

Linguagem C

Fontes:
http://www.juliobattisti.com.br/tutoriais/default.asp?cat=0001&ast=0042
http://www.dee.feis.unesp.br/graduacao/disciplinas/langc/modulo_linguagemc/modulo5.htm

Menu
Operadores
Definies
Printf
Scanf
If
Funes
Funes II
Matrizes
Matrizes II
Ponteiros
Ponteiros II

Operadores
Objetivos
Abordar os conceitos sobre os Operadores demonstrando o seu uso com exemplos para
um melhor aprendizado.

Pr-requisitos
necessrio que o leitor tenha acompanhado o artigo anterior, pois os artigos obedecem
a uma seqncia.

Nota: Este artigo faz parte do curso de Linguagem C Bsico.

Operadores
Os operadores indicam ao compilador a necessidade de se fazer manipulaes
matemticas ou lgicas.

Operadores aritmticos
Os operadores aritmticos so usados para calcular expresses matemticas. Sendo
classificados em duas categorias: os binrios ou unrios. Os operadores unrios atuam
na inverso de valores. Veja a tabela abaixo.

Operador binrio Descrio


=
Atribuio
+
Soma
Subtrao
/
Diviso
%
Modulo (obtm o resto da diviso)

Operador unrio Ao
Sinal negativo
+
Sinal positivo
Tabela Operadores aritmticos

O operador de atribuio (=) j foi estudado no artigo Linguagem C - Princpios


bsicos para explicar como inicializar uma varivel.

O exemplo abaixo imprime os resultado na tela das operaes de soma, subtrao,


multiplicao, diviso e o modulo entre dois nmeros dados. Ilustrando assim o uso dos
operadores aritmticos.

Sada do programa:

69+24=93
69-24=45
69x24=1656.000
69/24=2.875
69 mod 24=21.000

Operadores de incremento e decremento

O operador de incremento (++) soma 1 ao seu operando enquanto que o de decremento


(--) subtrai um. Eles podem ser pr-fixados ou ps-fixados conforme mostra a tabela
abaixo:

Operador Instruo
++

--

Ps-fixado Pr-fixado
var = var++; var = ++var;
var = var+1;
ou
ou
var++;
++var;
var = var--; var= --var;
var = var-1;
ou
ou
var--;
--var;

Tabela Operadores de incremento e decremento

No caso das instrues mostradas acima no existe diferena, podemos aplicar tanto o
ps-fixado quanto o pr-fixado. Mas quando esses operadores so usados em outras
expresses necessita-se de cuidado, pois o uso incorreto pode ocasionar resultados
inesperados. A diferena entre eles que o pr-fixado incrementa a varivel para depois
executar a instruo e a ps-fixado executa a instruo para depois fazer o incremento
da varivel. Veja o exemplo abaixo:

Sada do programa:

var=6
var2=6

O programa acima incrementa a varivel var e coloca o valor na var2 que no nosso caso
ser 6. J o cdigo abaixo coloca o valor da varivel var na var2 que 5 para depois
incrementar a varivel var.

Sada do programa:

var=6
var2=5

Operadores aritmticos de atribuies


So combinaes de operadores que simplificam as instrues e que geralmente so
usados por programadores experientes. Dessa forma uma instruo escrita da forma:

Var= var operador + expresso

Pode ser reduzida obedecendo sintaxe:

Var operador= expresso

Veja alguns exemplos utilizando duas variveis (var e expr) que devem ser declaradas
em seus programas.

Instruo normal
var = var + expr;
Var=var expr;
Var=var/expr;
Var=var*expr;

Instruo reduzida
var+=expr;
Var-=expr;
Var/=expr;
Var*=expr;

Operadores relacionais
Esses operadores so responsveis pelas comparaes de expresses nos programas. A
lista completa se encontra abaixo:

Operador
>
>=
<
<=
==
!=

Descrio
Maior
Maior igual
Menor
Menor igual
Igualdade
Diferente

Tabela Operadores relacionais

importante distinguir (=) de (==). O primeiro atribui um valor e o segundo comprara


expresses.

O prximo exemplo demonstra a analise de algumas expresses retornando 0 para falso


e 1 para verdadeiro. Esses dados so todos impressos na tela (veja a sada do programa).

Sada do programa:

Valor 0 indica expresso falsa e 1 expressao verdadeira.


98==10 0
98!=10 1
98<=10 0
98>=10 1
98<10 0
98 >10 1

Operadores lgicos
Os operados lgicos servem para interligar mais de uma operao relacional. E assim
como os relacionais retornam zero para falso e um para verdadeiro.

Operador

Descrio

&&
||
!

AND
OR
NOT (operador de negao)

Tabela Operadores lgicos

Exemplo de utilizao de operadores lgicos:

Sada do programa:

O nmero 76 esta entre 65 e 80

Nesse programa o operador lgico (&&) faz a ligao das operaes relacionais (x>65)
e (x<=80), verificando se o nmero dado (x) est entre essa faixa. A instruo if ser
estudada no prximo artigo.

Operadores bit a bit


Como j sabemos a linguagem C considerada de baixo nvel, pois permite a
manipulao de bits. Isto feito atravs dos operadores bit a bit listados a seguir.

Operador

Descrio

&
|
^
<<
>>

AND
OR
XOR (OR exclusivo)
Deslocamento para esquerda
Deslocamento para direita

Tabela operadores bit a bit

Embora a descrio na tabela seja parecida com as dos operadores Lgicos eles no
devem ser confundidos. Os operadores bit a bit so muito usados em rotinas de modens
e de impressoras.

Operador Cast
Tem como funo forar para que uma expresso seja de um determinado tipo. Sua
sintaxe :

(tipo de dado) expresso

O tipo de dado pode ser qualquer um dos definidos pelo padro ANSI. Um exemplo da
utilizao deste operador pode ser visto no programa mostrado neste artigo para
exemplificar o uso dos operadores aritmticos. Nesse programa o operador cast usado
para forar a diviso de dois nmeros inteiros ser do tipo float.

Operador Sizeof
Este operador usado em tempo de execuo e tem como objetivo retornar o tamanho
em bytes da varivel.

Sada do programa:

A variavel x do tipo float tem o tamanho=4 bytes


A variavel y do tipo double tem o tamanho=8 bytes
A variavel z do tipo char tem o tamanho=1 bytes

Precedncias
Precedncia a prioridade com que os operadores so executados pelo compilador.
Caso os operadores tenham o mesmo nvel de precedncia eles so analisados da
esquerda para direita.

Prioridades dos operadores aritmticos


Alta Incremento(++), decremento (--)
Menos unitrio (-)
Multiplicao(*), diviso(/), modulo(%)
Baixa Soma(+), subtrao(-)

A precedncia dos operadores pode ser mudada utilizando parentes. Para entender
melhor veja o exemplo abaixo, onde as duas expresses so iguais, porm o uso de um
parntese fez mudar a precedncia obtendo assim resultados diferentes.

4/2*5+1=11
4/2*(5+1)=12

Concluso
Conclui-se que os operadores so indispensveis em nossos programas e que a
linguagem C possui um nmero muito grande de operadores. Alguns inclusive sero
mostrados mais adiante, por exemplo, os operadores de ponteiro, devido serem muito
complexos.

Mdulo 2 Caractersticas e
Definies Gerais da Linguagem C
2.1 Palavras Reservadas na Linguagem C
Na Linguagem C existem palavras que so de uso reservado, ou seja, no podese us-las para escrever programas, por exemplo usando o nome de uma palavra
reservada para referenciar uma varivel. 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 padro
ANSI C so as relacionadas abaixo:
auto
break
case
char
const
continue
default
do

double
else
enum
extern
float
for
goto
if

int
long
register
return
short
signed
sizeof
static

struct
switch
typedef
union
unsigned
void
volatile
while

Como j foi dito no Mdulo 1, a Linguagem C diferencia letras maisculas e


minsculas, ou seja, char uma palavra reservada da Linguagem C mas CHAR ou
ChAr no . Reforando o que j foi mencionado, as palavras reservadas s iro
executar os comandos que lhes foram designados.

2.2 Nomes e Identificadores Usados na Linguagem C


A Linguagem C chama o que usado para referenciar variveis, funes, rtulo s e
vrios outros objetos definidos pelo usurio de identificadores. Quanto aos nomes ou
identificadores usados na declarao de variveis, deve-se considerar as seguintes
regras:
nomes de variveis comeam com uma letra ('A'..'Z', 'a'..'z') ou pelo underscore ('_');
aps podem ser seguidos dgitos, letras e underscores;
evitar o uso do '_' no primeiro caractere do identificador de uma varivel, pois este
tipo de identificadores de uso do sistema;
normalmente ao declarar-se uma varivel esta ser inicializada com zero. No se
deve, no entanto, contar que isto sempre seja verdadeiro, portanto inicializa-se sempre as
variveis.

Aqui esto alguns exemplos de nomes de identificadores corretos e incorretos:


Correto
count
test23
high_balance

Incorreto
1count
Ol! Aqui
high..balance

Em C os primeiros 32 caracteres de um nome de identificador so significantes.


Isso quer dizer que duas variveis com os 32 primeiros caracteres em comum, diferindo
somente no 33 , so consideradas iguais. Como voc deve lembrar, em C, letras
maisculas e minsculas so tratadas como diferentes e distintas umas das outras. Por
isso, count, Count e COUNT so trs identificadores distintos.

Um identificador no pode ser o mesmo que uma palavra reservada e no devem ter o
mesmo nome de uma funo tanto uma funo que voc tenha escrito como uma
funo de biblioteca da linguagem C.

2.3 Tipos e Dados


Quando um programa escrito em qualquer linguagem de programao
necessrio a definio de algumas variveis. Variveis so instncias em que sero
armazenados valores utilizados durante a execuo de programas. Estas variveis
podem ser modificadas para suportar diferentes tipos de dados. Na tabela abaixo
constam os tipos bsicos de dados da Linguagem C:

Tipo

Tamanho (em bits)

Intervalo

Char

-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

sem valor

2.3.1 Modificadores de Tipos


Possuindo os tipos bsicos de dados, pode-se ainda format-los para atender melhor
as necessidades de cada situao. Com exceo do tipo void, todos os outros tipos bsicos
podem ter modificadores precedendo-os. Voc pode ter como modificadores signed,
unsigned, long e short. Os modificadores signed, unsigned, long e short podem ser aplicados
aos tipos de base caractere e inteira. Entretanto, long, tambm pode ser aplicado ao tipo
double. A tabela a seguir mostra todas as combinaes permitidas dos tipos bsicos e dos
modificadores de tipo.
Tipo

Tamanho (em bits)

Intervalo

char

-128 a 127

unsigned char

0 a 255

signed char

-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

A linguagem C permite uma notao simplificada para declarao de inteiro unsigned,


short ou long. Voc pode simplesmente usar a palavra unsigned, short ou long sem o int. O int
est implcito. Por exemplo:
unsigned x;
unsigned int x;

declaram igualmente variveis inteiras sem sinal.


Variveis do tipo char podem ser usadas para armazenar valores outros que so
simplesmente o conjunto de caracteres ASCII. Uma varivel char pode ser usada tambm
como um pequeno inteiro com intervalo de 128 a 127, e no lugar de um inteiro quando a
situao no requer nmeros grandes.

2.4 Definio de Variveis


Variveis so instncias onde o programa em execuo coloca os dados que esto
sendo processados durante sua execuo. As variveis devem ser declaradas, ou seja, devem
ser definidos nome, tipo e algumas vezes seu valor inicial. As variveis so classificadas em
variveis locais e globais.
Variveis globais so aquelas declaradas fora do escopo das funes.
Variveis locais so aquelas declaradas no incio de um bloco e seus escopos esto
restritos aos blocos em que foram declaradas. A declarao de variveis locais deve
obrigatoriamente ser a primeira parte de um bloco, ou seja, deve vir logo aps um caractere
de abre chaves, '{'; e no deve ser intercalada com instrues ou comandos. Veja a sintaxe
para se declarar uma varivel:
<tipo> <nome>

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

2.5 Definio de Constantes


O conceito de constantes em linguagens de programao atribuir um certo valor
constante a um nome, e quando este nome for referenciado dentro do cdigo do programa,
ser utilizado nas operaes o valor atribudo a este nome. Ou seja, se for definida a constante
PI com o valor 3,1415926536, quando for encontrado no cdigo o nome PI, ser utilizado em

seu lugar o valor 3,1415926536. Na Linguagem C, constantes podem ser definidas da


seguinte maneira :
#define <nome_da_constante> valor

Exemplos:
#define PI 3,1415926536
#define SINAL "aberto"
#define MULT

A*B

Observe que na definio de uma constante no h o ; no final. Se for


colocado, este far parte do valor associado constante.

2.5.1 Constantes Hexadecimais e Octais


Em programao algumas vezes comum usar um sistema de numerao baseado em
8 ou 16 em vez de 10. O sistema numrico baseado em 8 chamado octal e usa os dgitos de 0
a 7. Em octal, o nmero 10 o mesmo que 8 em decimal. O sistema numrico de base 16
chamado hexadecimal e usa os dgitos de 0 a 9 mais as letras de A at F, que equivalem a 10,
11, 12, 13, 14 e 15. Por exemplo, o nmero hexadecimal 10 16 em decimal. Por causa da
freqncia com que estes dois sistemas numricos so usados, a linguagem C permite que se
especifique constantes inteiro em hexadecimal ou octal em vez de decimal, se preferir. Uma
constante hexadecimal deve comear com 0x (um zero seguido de um x), seguido pela
constante em formato hexadecimal. Uma constante octal comea com um zero. Aqui esto
alguns exemplos:
hex = 0xFF; /* 255 em decimal */
oct = 011; /* 9 em decimal */

2.5.2 Constantes Strings


Outro tipo de constante suportada pela Linguagem C o tipo string. Uma string um
conjunto de caracteres entre aspas. Por exemplo, voc um vencedor uma string.
No confunda strings com caractere. Uma constante caractere simples fica entre dois
apstrofos, por exemplo a. Entretanto a uma string que contm somente uma letra.

2.5.3 Cdigos de Barra Invertida


Colocar todas as constantes caractere entre aspas funciona para muitos
caracteres, mas alguns, como o retorno de carro, so impossveis de serem inseridos em
uma string a partir do teclado. Por isso, a linguagem C fornece constantes caractere mais
barra invertida especiais. Estes cdigos so mostrados na tabela a seguir:

Cdigo
\b
\n
\t
\
\\
\a
\xN

Significado
Retrocesso

Nova linha
Tabulao horizontal
Apstrofo
Barra invertida
Sinal sonoro
Constante hexadecimal

Cdigo
\f
\r
\
\0
\v
\N

Significado
Alimentao de formulrio
Retorno de carro
Aspas
Nulo
Tabulao vertical
Constante octal

Usa-se um cdigo de barra invertida exatamente da mesma maneira como usa qualquer
outro caractere. Por exemplo:
ch = \t;
printf (este um teste\n);

Esse fragmento de cdigo primeiro atribui uma tabulao a ch e, ento, imprime este
um teste na tela, seguido de uma nova linha.

2.6 Operadores
A linguagem C muito rica em operadores internos. Um operador um smbolo que
diz ao compilador para realizar manipulaes matemticas e lgicas especficas. A linguagem C
possui trs classes gerais de operadores: aritmticos, relacionais e lgicos e bit-a-bit.

2.6.1 Operador de atribuio


O operador = atribui um valor ou resultado de uma expresso contida a sua direita
para a varivel especificada a sua esquerda. Exemplos:
a = 10;
b = c * valor + getval(x);
a = b = c = 1; /*Aceita associao sucessiva de valores*/

2.6.2 Operadores Aritmticos


So aqueles que operam sobre nmeros e expresses, resultando valores numricos. So
eles:
Operador
+
*
/
%

Ao
Soma
subtrao
multiplicao
diviso
mdulo da diviso (resto da diviso inteira)

sinal negativo (operador unrio)

2.6.3 Operadores Relacionais


Operam sobre expresses, resultando valores lgicos de TRUE (verdadeiro) ou FALSE
(falso). so eles:
Operador

Ao

>
>=
<
<=

Maior
maior ou igual
Menor
menor ou igual
Igual
no igual (diferente)

==
!=
Ateno!

No existem os operadores relacionais: =<, => e <>.


No confunda a atribuio (=) com a comparao (==).

2.6.4 Operadores Lgicos


Operam sobre expresses, resultando valores lgicos de TRUE (verdadeiro) ou FALSE
(falso). Possuem a caracterstica de short circuit, ou seja, sua execuo curta e s
executada at o ponto necessrio. So eles:
Operador
&&
||
!

Ao
operao AND
operao OR
operador de negao NOT (operador unrio)

Exemplos de short circuit:


(a == b) && (b == c)
*/

/*

Se a != b no avalia o resto da expresso

(a == b) || (b == c)
*/

/*

Se a == b no avalia o resto da expresso

2.6.5 Manipulao de bits


A manipulao feita em todos os bits da varivel a qual no pode ser do tipo float ou
double. Os operadores que manipulam bits esto relacionados abaixo:
Operador

&
|

Ao
bit and
bit or

^
<<
>>
~

bit xor - exclusive or


Rotao a esquerda
Rotao a direita
bit not (complemento)

Observao: x << n ir rotacionar n vezes a varivel x esquerda.

2.6.6 Operadores de assinalamento


expresso da seguinte forma: (operadores combinados)
var = var op expr

->

var op = expr

Onde tempos op como um dos seguintes operadores:


Operador
+
*
/
%
>>
<<
&
^
|

Ao
Soma
Subtrao
Multiplicao
Diviso
mdulo (resto da diviso)
Rotao a direita
Rotao a esquerda
And
xor - exclusive or
Or

Exemplo de aplicao:
i+= 2; /* equivalente a: i = i + 2 */
j-= 3; /* equivalente a: j = j 3 */
k >>= 3; /* equivalente a: k = k >> 3;*/
z &= flag; /* equivalente a: z = z & flag;*/

2.6.7 Operadores de Pr e Ps-Incremento


Operadores de pr e ps-incremento so aqueles usados quando necessrio
incrementar ou decrementar um determinado valor.

As operaes abaixo podem ser representadas assim:


i = i + 1;

i = ++i;

++i;

i = i 1;

i = --i;

--i;

z = a; a = a + 1;

z = a++;

z = a;

z = a--;

a = a 1;

a = a + 1; z = a;

z = ++a;

a = a - 1; z = a;

z = --a;

2.6.8 - Operadores de Endereo


So operadores usados com ponteiros, para acesso a endereos de memria.
Operador
&
*

Significado
endereo de uma varivel
contedo do endereo especificado

Exemplos:
int var, *x;
x = &var;
var = *x;

2.7 Tabela de Operadores da Linguagem C


Operador
+
!
~
&
*
sizeof
++
-*
/
/
%
+
>>
<<
>
>=

Funo
menos unrio
mais unrio
negao lgica
bitwise not
endereo de
referncia a ptr
tamanho de var
incremento
decremento
multiplicao
diviso inteira
diviso real
resto da diviso
soma
subtrao
shift right
shift left
maior que
maior ou igual a

Exemplo C
a = -b;
a = +b ;
! flag
a = ~b ;
a = &b ;
a = *ptr ;
a = sizeof(b) ;
++a; ou a++;
--a; ou a--;
a = b * c;
a = b / c;
a = b / c;
a = b % c;
a = b + c;
a = b c;
a = b >> n;
a = b << n;
a>b
a >= b

<
<=
==
!=
&
|
^
&&
||
=
OP=

menor que
menor ou igual a
igual a
diferente de
bitwise AND
bitwise OR
bitwise XOR
logical AND
logical OR
assinalamento
assinalamento

a<b
a <= b
a == b
a != b
a = b & c;
a = b | c;
a = b ^ c;
flag1 && flag2
flag1 || flag2
a = b;
a OP= b;

2.8 Expresses
Operadores, constantes e variveis constituem expresses. Uma expresso em C
qualquer combinao vlida dessas partes. Uma vez que muitas expresses tendem a seguir as
regras gerais da lgebra, estas regras so freqentemente consideradas. Entretanto, existem
alguns aspectos das expresses que esto especificamente relacionadas com a linguagem C e
sero discutidas agora.

2.8.1 Converses de Tipos em Expresses


Quando constantes e variveis de tipos diferentes so misturadas em uma expresso,
elas so convertidas para o mesmo tipo. O compilador C converter todos os operandos para o
tipo do operando maior. Isso feito na base de operao a operao, como descrito nestas
regras de converso de tipos:
Todos os chars e shor ints so convertidos para ints.
Todos os floats so convertidos para doubles;
Para todos os pares de operandos, se um deles um long double, o outro operando
convertido para uma long double. Se um dos operandos double, o outro convertido
para double. Se um long, o outro convertido para long. Se um unsigned, o outro
convertido para unsigned.
Uma vez que essas regras de converso tenham sido aplicadas, cada par de operandos
ser do mesmo tipo e o resultado de cada operao ter o mesmo tipo dos dois operandos.
Note que a regra 2 tem muitas condies que devem ser aplicada em seqncia.
Por exemplo, considere a converso de tipos que ocorre na expresso a seguir:

Primeiro, o caractere ch convertido para um inteiro e float f convertido para


double. Ento, o resultado de ch/i convertido para um double, j que f * d um double. O
resultado final um double, tendo em vista que, neste caso, os dois operandos so double.

2.8.2 - Modeladores (CASTS)


possvel forar uma expresso a ser de um tipo especfico usando-se uma construo
chamada de modelador. A forma geral de um modelador :
(tipo) expresso
(float) x / 2;

Onde tipo um dos tipos dado-padro da linguagem C. Por exemplo, se x um inteiro


e voc quer certificar-se de que a expresso x/2 resulta em um tipo float, garantindo um
componente fracionrio, pode escrever:
Aqui, o modelador (float) associado com o x, o que faz com que o 2 seja elevado ao
tipo float e o resultado seja um float. Entretanto, tome cuidado: se voc escrever a expresso
acima como segue, o componente fracionrio no ser considerado:
(float) (x / 2);

Neste caso, uma diviso de inteiros levada a cabo e o resultado transformado em


float.

Modeladores so freqentemente considerados como operadores. Como um operador,


um modelador unrio e tem a mesma precedncia de qualquer outro operador unrio.

2.8.3 Espaamento e Parnteses

Pode-se colocar espaos numa expresso para torn-la mais legvel. O uso de parnteses
redundantes ou adicionais no causar erros ou diminuir a velocidade de execuo da
expresso. estimulado o uso de parnteses para tornar clara e exata a ordem de
avaliao, tanto para voc como para outros que precisarem entender o seu programa
mais tarde. Por exemplo, as duas expresses seguintes so as mesmas:
x=645/(num_entry)-y*(3217/balance);
x = 645 / (num_entry) y * (3127 / balance);

Qual das duas expresses seguintes mais fcil de ler?


x=y/3-24*temp-127;
x = (y/3) (34*temp) 127;

2.9 Sntese do Mdulo


apresentada, a seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
2.1 Palavras Reservadas em Linguagem C: foi visto neste item, que na Linguagem
C existem palavras que so de uso reservado, ou seja, referenciam comandos ou aes e,
portanto, no podem ser usadas pelo programador para referenciar por exemplo uma varivel
em um determinado programa. Foi apresentado uma tabela relacionando as palavras
reservadas da Linguagem C.
2.2 Nomes e Identificadores Usados na Linguagem C: a Linguagem C chama o que
usado para referenciar variveis, funes, rtulos e vrios outros objetos definidos pelo
usurio de identificadores. Em C os primeiros 32 caracteres de um nome de identificador so
significantes. Um identificador no pode ser o mesmo que uma palavra reservada e no devem
ter o mesmo nome de uma funo.
2.3 Tipos e Dados: variveis so instncias em que sero armazenados valores
utilizados durante a execuo de programas. Estas variveis podem ser modificadas para
suportar diferentes tipos de dados. Foi visto que os tipos bsicos de dados da Linguagem C
so: char, int, float, doubl, void.
2.3.1 Modificadores de Tipos: possuindo os tipos bsicos de dados, pode-se ainda
format-los para atender melhor as necessidades de cada situao. Com exceo do tipo void,
todos os outros tipos bsicos podem ter modificadores precedendo-os. Foi apresentado uma
tabela mostrando todas as combinaes permitidas dos tipos bsicos e dos modificadores de
tipo.
2.4 Definio de Variveis: foi visto que variveis so instncias onde o programa
em execuo coloca os dados que esto sendo processados durante sua execuo. As variveis

devem ser declaradas, ou seja, devem ser definidos nome, tipo e algumas vezes seu valor
inicial. As variveis so classificadas em variveis locais e globais.
2.5 Definio de Constantes: definimos uma constante quando atribumos um
certo valor constante um nome. Quando este nome referenciado dentro de um programa,
ser utilizado nas operaes o valor atribudo a este nome.
2.5.1 Constantes Hexadecimais e Octais: em programao algumas vezes
comum usar um sistema de numerao baseado em 8 ou 16 em vez de 10. Por causa da
freqncia com que estes dois sistemas numricos so usados, a linguagem C permite que se
especifique constantes inteiro em hexadecimal ou octal em vez de decimal, se preferir.
2.5.2 Constantes Strings: Outro tipo de constante suportada pela Linguagem C o
tipo string. Uma string um conjunto de caracteres entre aspas. Por exemplo, voc um
vencedor uma string.
2.5.3 Cdigos de Barra Invertida: colocar todas as constantes caractere entre
aspas funciona para muitos caracteres, mas alguns, como o retorno de carro, so impossveis
de serem inseridos em uma string a partir do teclado. Por isso, a linguagem C fornece
constantes caractere mais barra invertida especiais. Estes cdigos foram mostrados em uma
tabela.
2.6 Operadores: Um operador um smbolo que diz ao compilador para realizar
manipulaes matemticas e lgicas especficas. A linguagem C possui trs classes gerais de
operadores: aritmticos, relacionais e lgicos e bit-a-bit.
2.6.1 Operador de atribuio: o operador = atribui um valor ou resultado de
uma expresso contida a sua direita para a varivel especificada a sua esquerda.
2.6.2 Operadores Aritmticos: so aqueles que operam sobre nmeros e
expresses, resultando valores numricos.
2.6.3 Operadores Relacionais: operam sobre expresses, resultando valores
lgicos de TRUE (verdadeiro) ou FALSE (falso).
2.6.4 Operadores Lgicos: operam sobre expresses, resultando valores lgicos de
TRUE (verdadeiro) ou FALSE (falso). Possuem a caracterstica de short circuit, ou seja, sua
execuo curta e s executada at o ponto necessrio.
2.6.5 Manipulao de bits: a manipulao feita em todos os bits da varivel a
qual no pode ser do tipo float ou double. Os operadores que manipulam bits foram
relacionados em uma tabela.
2.6.6 Operadores de assinalamento: assinalam o uso de uma operao,
combinando operadores de tal forma a diminuir o cdigo e facilitar sua posterior
compreenso.
2.6.7 Operadores de Pr e Ps-Incremento: operadores de pr e ps-incremento
so aqueles usados quando necessrio incrementar ou decrementar um determinado valor.

2.6.8 Operadores de Endereo: so operadores usados com ponteiros, para


acesso a endereos de memria.
2.7 Tabela de Operadores da Linguagem C: foi apresentada uma tabela com os
operadores disponveis na Linguagem C.
2.8 Expresses: operadores, constantes e variveis constituem expresses. Uma
expresso em C qualquer combinao vlida dessas partes.
2.8.1 Converses de Tipos em Expresses: quando constantes e variveis de tipos
diferentes so misturadas em uma expresso, elas so convertidas para o mesmo tipo. O
compilador C converter todos os operandos para o tipo do operando maior.
2.8.2 Modeladores (CASTS): possvel forar uma expresso a ser de um tipo
especfico usando-se uma construo chamada de modelador. Modeladores so
freqentemente considerados como operadores. Como um operador, um modelador unrio
e tem a mesma precedncia de qualquer outro operador unrio.
2.8.3 Espaamento e Parnteses: pode-se colocar espaos numa expresso para
torn-la mais legvel. O uso de parnteses redundantes ou adicionais no causar erros ou
diminuir a velocidade de execuo da expresso

Estudo das Funes PRINTF() e SCANF()


4.1 Funo PRINTF()
Quando necessrio imprimir na tela um dado, um valor, uma string ou mesmo um
endereo de memria, usa-se a funo printf(). Quando o programa usa a funo printf(), as
informaes que instrui printf() a imprimir so chamadas parmetros ou argumentos de
printf(). A estrutura bsica da funo printf() dada a seguir:
printf ("string de controle", lista de argumentos);

A string de controle contm tanto caracteres para serem impressos na tela como
cdigos de formato que especificam como apresentar o restante dos argumentos.
Quando os programas trabalharem com variveis, ser possvel usar printf() para exibir

os valores de cada varivel. A funo printf() suporta mais de um parmetro. O primeiro


parmetro precisa ser sempre uma string de caracteres. Pode-se fazer os parmetros que
seguem a primeira string de caracteres serem nmeros, expresses, variveis, ou at
outras strings de caracteres. Quando for necessrio que printf() exiba um valor ou uma
varivel, preciso fornecer informaes sobre o tipo da varivel dentro do primeiro
parmetro. Alm de especificar caracteres dentro do primeiro parmetro, pode-se incluir
especificadores de formato, que instruem printf() como imprimir os outros parmetros.
Esses especificadores de formato tm 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:
Cdigo
%c

Significado

Exibe um caractere
%d
%i
%e
%E
%f
%g
%G
%o
%s
%u
%x
%X
%%
%p

Exibe um inteiro em formato decimal


Exibe um inteiro
Exibe um nmero em notao cientfica (com e minsculo)
Exibe um nmero em notao cientfica (com E maisculo)
Exibe um ponto flutuante em formato decimal
Usa %e ou %f, o que for menor
O mesmo que %g, s que um E maisculo usado se o formato %e for
escolhido
Exibe um nmero em notao octal
Exibe uma string
Exibe um decimal sem sinal
Exibe um nmero em hexadecimal com letras minsculas
Exibe um nmero em hexadecimal com letras maisculas
Exibe um sinal de %
Exibe um ponteiro

4.1.1 Exibindo Valores do Tipo int Usando Printf()


Para exibir valores do tipo int com printf(), usa-se o especificador de formato %d. O
programa a seguir usa o especificador de formato %d para exibir valores e variveis 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);
}

Uma observao importante que muitos compiladores C tratam o especificador


de formato %i como idntico 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.

4.1.2 Exibindo um Valor Inteiro Octal ou Hexadecimal


Muitas vezes nos programas preciso exibir um valor inteiro em seu formato octal
(base 8) ou hexadecimal (base 16). O especificador de formato %o (letra "o", no zero) instrui
printf() a exibir uma valor em octal. Da mesma forma, %x e %X instruem printf() a exibir uma
valor em hexadecimal, sendo que no primeiro caso em minsculo e no segundo imprime os
valores em maisculo.

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);
}

4.1.3 Exibindo Valores do Tipo Unsigned Int


Para exibir valores do tipo unsigned int com a funo printf(), deve-se usar o
especificador de formato %u. 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);
}

4.1.4 Exibindo Valores do Tipo Long Int


Para exibir valores do tipo long int com a funo printf(), deve-se usar o especificador
de formato %ld. 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 milho %ld\n", um_milhao);
printf ("Um milho %d\n", um_milhao);
}

4.1.5 Exibindo Valores do Tipo Float


Para exibir valores do tipo float com a funo printf(), deve-se usar o especificador de
formato %f. 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);

4.1.6 Exibindo Valores do Tipo Char


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

4.1.7 Exibindo Valores de Ponto Flutuante em um Formato Exponencial


Para exibir um valor em ponto flutuante em um formato exponencial com a
funo printf(), deve-se usar o especificador de formato %e ou %E. A diferena entre
os dois que %E instrui printf() a usar uma letra E maiscula na sada.
#include <stdio.h>
void main(void)
{
float pi = 3.14159;
float raio = 2.0031;
printf("A rea do crculo %e\n", 2 * pi * raio);
printf("A rea do crculo %E\n", 2 * pi * raio);
}

4.1.8 Exibindo Valores em Ponto Flutuante


A funo printf() tambm suporta os especificadores %g e %G para imprimir
valores em ponto flutuante. Quando usa-se esses especificadores de formato, printf()
decide se deve usar o formato %f ou %e, dependendo da tcnica que exibir a sada no
formato mais significativo para o usurio.
Veja o exemplo que ilustra o uso do especificador %g:
#include <stdio.h>
void main(void)

{
printf("Exibir 0.1234 resulta em %g\n", 0.1234);
printf("Exibir 0.00001234 resulta em %g\n", 0.00001234);
}

4.1.9 Exibindo uma String de Caracteres


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

4.1.10 Exibindo um Endereo de Ponteiro


Para exibir um endereo de ponteiro com a funo printf(), deve-se usar o
especificador de formato %p.
A seguir um exemplo que usa %p para exibir um endereo de memria.
#include <stdio.h>
void main(void)
{
int valor;
printf("O endereo da varivel valor %p\n", &valor);
}

4.1.11 - Precedendo um Valor com um Sinal de Adio ou de Subtrao


Em muitos programas necessrio 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 adio imediatamente aps o % no especificador de formato. O
exemplo a seguir ilustra o uso do sinal de adio 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 so %+d and %+d\n",neg_int,
pos_int);
printf("Os valores em ponto flutuante so %+f %+f\n", neg_flt,
pos_flt);
}

4.1.12 Formatando um Valor Inteiro


Usando o especificador de formato %d, ser possvel instruir printf() a exibir um
nmero mnimo de caracteres. O dgito que for colocado aps o % especifica o nmero
mnimo de caracteres que printf() usar para exibir um valor inteiro. Por exemplo, caso
seja especificado %5d e o valor a ser exibido for 10, printf() predecer o valor com trs
espaos. Observe que o valor especifica o nmero mnimo de caracteres que a sada
consumir. Se o valor a ser exibido requer mais caracteres do que o especificado,
printf() usar o nmero 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);
}

4.1.13 - Sada de Inteiros Preenchida com Zeros

No item anterior, foi visto como formatar uma sada instruindo printf() a exibir um
determinado nmero de dgitos. No caso anterior, printf() colocava espaos antes do valor a
ser exibido, mas possvel configur-lo de tal maneira que ele exiba zeros antes do valor ou
caracter que necessrio exibir. Esses zeros so chamados de zeros de preenchimento. Para
instruir printf() a preencher um valor com zeros, coloca-se um 0 (zero) imediatamente aps o
% no especificador de formato, antes do nmero desejado de dgitos. 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);
}

4.1.14 Exibindo um Prefixo Antes dos Valores Octais ou Decimais


Em muitos programas que apresentam valores octais ou hexadecimais, em muitos casos
necessrio 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 # imediatamente aps 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 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);

4.1.15 Formatando um Valor em Ponto Flutuante


No item 3.1.11 foi visto como formatar um valor inteiro colocando o nmero desejado
de dgitos imediatamente aps o % no especificador de formato %d. Usando uma tcnica
similar, printf() permite formatar a sada em ponto flutuante. Quando formata-se um valor em
ponto flutuante especifica dois valores. O primeiro valor diz a printf() o nmero mnimo de
caracteres a serem exibidos. O segundo valor diz a printf() o nmero de dgitos a serem
exibidos direita do ponto decimal. O exemplo abaixo ilustra esta tcnica.
#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);
}

4.1.16 Formatando a Sada Exponencial


No item anterior foi visto como usar o especificador de formato %f para formatar
valores em ponto flutuante. Usando tcnicas de formatao similares, pode-se instruir pintf()
a exibir a sada 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.3e\n", valor);
printf ("%12.5e\n", valor);
}

4.1.17 Justificando Esquerda a Sada de Printf()

Por padro, quando for exibido o texto usando os caracteres de formatao, printf()
exibir o texto justificado direita. Dependendo do programa, algumas vezes necessrio que
printf() justifique o texto esquerda. Para justificar o texto esquerda, coloque um sinal de
subtrao (-) imediatamente aps o % no especificador de formato. O exemplo a seguir ilustra
o uso desta tcnica de formatao.
#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);
}

4.1.18 Combinando os Especificadores de Formato de Printf()


Muitas vezes por rapidez e para que o cdigo 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 aps o %. Veja um exemplo.
#include <stdio.h>
void main(void)
{
int int_valor = 5;
printf("Justificado esquerda com sinal %-+3d\n", int_valor);
}

4.1.19 Trabalhando com os Caracteres Escape de Printf()


Quando trabalha-se com string de caracteres, pode-se usar caracteres especiais, tais
como tabulao, retorno do carro, ou alimentao de linha. A Linguagem C define vrios

caracteres de escape (referenciados no Mdulo 2 item 2.4.3) para facilitar para voc a incluso
de caracteres especiais dentro de uma string. Um exemplo o uso do caracter de nova linha
(\n) para avanar a sada para o incio da prxima linha.
printf("Linha 1\nLinha2\nLinha 3\n");

4.1.20 Determinando o Nmero de Caracteres que Printf() Exibiu


Quando usa-se o especificador de formato %n, printf() atribuir uma varivel (passada
por ponteiro) um contador do nmero 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.1.21 Usando o Valor de Retorno de Printf()


Usar o especificador de formato %n um modo de garantir que printf() teve sucesso ao
exibir sua sada. Alm disso, quando printf() termina, ele retorna o nmero total de caracteres
que escreveu. Se printf() encontrar um erro, retornar a constante EOF (que como ser visto
no mdulo 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");


}

4.2 Funo SCANF()


A funo scanf( ) uma das funes de entrada de dados da Linguagem C, que pode
ser usada para ler virtualmente qualquer tipo de dado inserido por meio do teclado,
freqentemente ela usada para a entrada de nmeros inteiros ou de ponto flutuante. A
forma geral da funo scanf( ) :
scanf (string de controle, lista de argumentos);

Os especificadores de formato de entrada so precedidos por um sinal % e dizem


funo scanf( ) qual tipo de dado deve ser lido em seguida. Esses cdigos so listados na tabela
a seguir.
Cdigo
%c
%d
%i
%u
%e
%f
%g
%o
%s
%x
%p

Significado
L um nico caractere
L um decimal inteiro
L um decimal inteiro (no pode ser octal ou hexadecimal)
L um decimal sem sinal
L um nmero em ponto flutuante com sinal opcional
L um nmero em ponto flutuante com ponto opcional
L um nmero em ponto flutuante com expoente opcional (double)
L um nmero em base octal
L uma string
L um nmero em base hexadecimal
L um ponteiro

Os caracteres de converso d, i, o, u e x podem ser precedidos por h para indicarem


que um apontador para short ao invs de int aparece na lista de argumentos, ou por l (letra
ele) para indicar que um apontador para long aparece na lista de argumentos.
Semelhantemente, os caracteres de converso e, f e g podem ser precedidos por l (letra ele)
para indicarem que um apontador para double ao invs de float est na lista de argumentos.
A cadeia de formato geralmente contm especificaes de converso, que so usadas
para controlar a converso da entrada. A cadeia de formato pode conter:
espaos, tabulaes e novas linhas, que sero ignorados;
caracteres comuns (no %), que devem combinar com o prximo caractere
no espao do fluxo de entrada;
especificaes de converso, consistindo no caractere %, um caractere *
opcional de supresso de atribuio, um nmero opcional especificando um tamanho mximo
do campo, um h ou l opcional indicando o tamanho do destino, e um caractere de converso.

4.2.1 Usando Caracteres em Scanf() que Sero Descartados


Um caractere que no seja um espao em branco faz com que a funo scanf( ) leia e
descarte o caractere correspondente. Por exemplo, %d,%d faz com que a funo scanf() leia um
inteiro, ento, leia uma vrgula (que ser descartada) e, finalmente, leia outro inteiro. Se o

caractere especificado no encontrado, a funo scanf( ) terminar. Pode-se usar esta tcnica
para separa os especificadores de formato, tornando o cdigo mais legvel.
#include <stdio.h>
void main(void)
{
int a,b;
scanf("%d,%d", &a, &b);
}

4.2.2 - Lendo Valores em Variveis


Todas as variveis usadas para receber valores por meio da funo scanf() devero ser
passadas pelos seus endereos. Por exemplo, para ler um inteiro em uma varivel count,
poderia usar a seguinte chamada funo scanf():
#include <stdio.h>
void main(void)
{
int count;
scanf("%d ", &count);
}

4.2.3 Lendo String de Caracteres


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

Nesse caso, nome j um endereo e no precisa ser precedido pelo operador &.

4.2.4 Formatando a Entrada de Scanf()

Os itens de dados de entrada devem ser separados por espaos, tabulaes ou novas
linhas. Pontuaes como vrgula, ponto-e-vrgula e semelhantes no contam como
operadores. Isso significa que scanf(%d%d, &r, &c); aceitar uma entrada dos nmeros 10
20, mas falhar com 10,20. Como na funo printf( ), os cdigos de formato da funo scanf( )
devem ser correspondidos na ordem com as variveis que esto recebendo a entrada na lista
de argumento.
Um * colocado depois do % e antes do cdigo de formato ler um dado de um tipo
especificado, mas suprimir a sua atribuio. Assim, scanf(%d%*c%d, &x, &y); dando-se a
entrada 10/20, colocar o valor 10 em x descartando o sinal de diviso, e dar a y o valor 20.
Ainda que espaos, tabulaes e novas linhas sejam usados como separadores de
campos, quando da leitura de um nico caractere, esses ltimos so lidos como qualquer
outro caractere. Por exemplo, com uma entrada de x y; scanf(%c%c%c, &a, &b, &c);
retornar com o caractere x em a, um espao em b e o caractere y em c.

4.2.5 Determinando o Nmero Mximo de Caracteres a ser Lido


Os comandos de formato podem especificar um campo modificador de comprimento
mximo. Esse modificador um nmero inteiro colocado entre o sinal % e o cdigo de
comando de formato, que limita o nmero de caracteres lidos para qualquer campo. Por
exemplo, para ler no mais que 20 caracteres em str, voc pode escrever:
#include <stdio.h>
void main(void)
{
char str[40];
scanf("%20s", str);
}

Se o apontador de entrada maior do que 20 caracteres, uma chamada subseqente


para entrada comear onde ela pra. Por exemplo, se for digitado
ABCDEFGHIJKLMNOPQRSTUVWXYZ em resposta chamada scanf( ), nesse exemplo, somente
os 20 primeiros caracteres, at o T, sero colocados em str por causa do especificador de
tamanho mximo. Isso significa que os caracteres restantes UVWXYZ no so usados. Se uma
outra chamada funo scanf( ) feita, tal como scanf(%s, str); ento UVWXYZ colocado
em str. A entrada para o campo pode ser terminada, antes que o campo de comprimento
mximo seja alcanado, se um caractere de espao em branco encontrado. Nesse caso, a
funo scanf( ) move-se para o prximo campo.

4.2.6 - Lendo Somente Caracteres Pr-Determinados


A funo scanf( ) inclui tambm uma caracterstica muito poderosa chamada scanset.
Um scanset define uma lista de caracteres que sero correspondidos por scanf(). A funo
scanf( ) continuar a ler caracteres enquanto eles estiverem no scanset. Assim que um
caractere entrado no corresponder a qualquer um do scanset, a funo scanf( ) segue para o
prximo especificador de formato (se existir). Um scanset definido colocando-se uma lista de
caracteres que quer-se que seja examinada entre chaves. A chave inicial deve ser prefixada por

um sinal de porcentagem. Por exemplo, este scanset diz funo scanf( ) para ler somente os
dgitos de 0 a 9: %[1234567890].

O argumento correspondente a scanset deve ser uma varivel string.


Aps retornar de funo scanf( ), a varivel conter uma string terminada com um nulo
com os caracteres lidos. Para ver como isso funciona, considere este programa:
#include <stdio.h>
#include <conio.h>
void main()
{
char s1[80], s2[80];
scanf (%[1234567890]%s, s1, s2);
printf (\n%s| |%s, s1, s2);
getch();
}

Pode-se testar esse programa usando a entrada 123456789abcdefg987654 seguida


por um retorno de carro. O programa exibir, ento: 123456789| |abcdefg987654. Uma vez
que a no faz parte do scanset, a funo scanf( ) pra de ler os caracteres em s1 quando ele
encontrado e os caracteres restantes so colocados em s2.
Voc pode especificar um intervalo dentro de um scanset usando um hfen. Por
exemplo, isto diz funo scanf( ) para aceitar os caracteres de A a Z:
%[A-Z]
Pode-se especificar mais de um intervalo dentro de um scanset. Por exemplo, este
programa l dgitos e letras. Ele tambm ilustra que pode-se usar o especificador de campo
mximo como um scanset.
#include <stdio.h>
#include <conio.h>
void main()
{
char str[80];
printf (Informe dgitos e letras: );

scanf (%78[a-z0-9], str);


printf (\n%s, str);
getch();
}

Pode-se especificar um conjunto invertido se o primeiro caractere um ^. Quando


est presente, o ^ instrui a funo scanf( ) a aceitar quaisquer caracteres que no esto
definidos no scanset.
Um ponto importante a lembrar que o scanset difere letras minsculas de
maisculas. Portanto, se quiser examinar tanto letras maisculas como minsculas, deve
especific-las individualmente.

4.3 - Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
4.1 Funo PRINTF(): neste item foi apresentada uma introduo da funo
printf(), listando suas caractersticas e propriedades bem como sua estrutura.
4.1.1 Exibindo Valores do Tipo int Usando Printf(): neste item foi mostrado como
possvel exibir uma sada printf() para valores inteiros, usando-se o especificador de formato
%d.
4.1.2 Exibindo um Valor Inteiro Octal ou Hexadecimal: foi visto que possvel
exibir um valor inteiro em seu formato octal (base 8) ou hexadecimal (base 16) atravs dos
especificadores de formato %o, %x e %X.
4.1.3 Exibindo Valores do Tipo Unsigned Int: neste item foi apresentado como
exibir valores do tipo unsigned int com a funo printf(), usando o especificador de formato
%u.
4.1.4 Exibindo Valores do Tipo Long Int: foi visto que para exibir valores do tipo
long int com a funo printf(), deve-se usar o especificador de formato %ld.
4.1.5 Exibindo Valores do Tipo Float: foi visto que para exibir valores do tipo float
com a funo printf(), deve-se usar o especificador de formato %f.
4.1.6 Exibindo Valores do Tipo Char: foi visto que para exibir valores do tipo char
com a funo printf(), deve-se usar o especificador de formato %c.
4.1.7 Exibindo Valores de Ponto Flutuante em um Formato Exponencial: foi visto
que para exibir um valor em ponto flutuante em um formato exponencial com a funo
printf(), deve-se usar o especificador de formato %e ou %E.
4.1.8 Exibindo Valores em Ponto Flutuante: foi visto que a funo printf()
tambm suporta os especificadores %g e %G para imprimir valores em ponto flutuante.

4.1.9 Exibindo uma String de Caracteres: foi visto que para exibir uma string de
caracteres com a funo printf(), deve-se usar o especificador de formato %s.
4.1.10 Exibindo um Endereo de Ponteiro: foi visto que para exibir um endereo
de ponteiro com a funo printf(), deve-se usar o especificador de formato %p.
4.1.11 Precedendo um Valor com um Sinal de Adio ou de Subtrao: foi visto
que para instruir printf() a exibir um sinal de um valor, deve-se incluir um sinal de adio
imediatamente aps o % no especificador de formato.
4.1.12 Formatando um Valor Inteiro: neste item foi visto como configurar printf()
de tal forma que sua valores a serem exibidos tenha seu formato de sada na tela especificado
pelo programador.
4.1.13 Sada de Inteiros Preenchida com Zeros: foi visto neste item que
possvel configurar printf() de tal maneira que ele exiba zeros antes do valor ou caracter que
necessrio exibir.
4.1.14 Exibindo um Prefixo Antes dos Valores Octais ou Decimais: foi visto como
preceder os valores em octal com um zero, e os hexadecimais com 0x .
4.1.15 Formatando um Valor em Ponto Flutuante: foi visto que quando formatase um valor em ponto flutuante especifica dois valores. O primeiro valor diz a printf() o
nmero mnimo de caracteres a serem exibidos. O segundo valor diz a printf() o nmero de
dgitos a serem exibidos direita do ponto decimal. Com isto foi apresentada uma tcnica de
formatao de printf().
4.1.16 Formatando a Sada Exponencial: foi visto como configurar printf() de tal
forma a exibir a sada em ponto flutuante em um formato exponencial.
4.1.17 Justificando Esquerda a Sada de Printf(): foi apresentado que para
justificar o texto esquerda, coloca-se um sinal de subtrao (-) imediatamente aps o % no
especificador de formato.
4.1.18 Combinando os Especificadores de Formato de Printf(): apresentado
neste item a possibilidade de aproveitar dois ou mais especificadores de formato de printf()
com intuito de deixar o cdigo mais enxuto.
4.1.19 Trabalhando com os Caracteres Escape de Printf():. Foi visto que a
Linguagem C define vrios caracteres de escape (referenciados no Mdulo 2 item 2.4.3) para
facilitar para voc a incluso de caracteres especiais dentro de uma string.
4.1.20 Determinando o Nmero de Caracteres que Printf() Exibiu: Foi visto que
quando usa-se o especificador de formato %n, printf() atribuir uma varivel (passada por
ponteiro) um contador do nmero de caracteres que printf() exibiu.
4.1.21 Usando o Valor de Retorno de Printf(): foi mostrado que possvel utilizar
o valor que printf() retorna quando ele finaliza suas tarefas. Este valor retornado pode ser
utilizado de vrias formas, variando o uso de acordo com as caractersticas do programa.
4.2 Funo SCANF(): foi feita neste item uma introduo funo scanf(). Foi
mostado que a funo scanf( ) uma das funes de entrada de dados da Linguagem C, que

pode ser usada para ler virtualmente qualquer tipo de dado inserido por meio do teclado.
Alm da introduo funo foi apresentada sua estrutura e caractersticas.
4.2.1 Usando Caracteres em Scanf() que Sero Descartados: foi mostrado que
possvel inserir dentro da funo scanf() caracteres que no sero lidos. Estes caracteres
servem apenas na tornar o cdigo mais legvel e de fcil entendimento.
4.2.2 Lendo Valores em Variveis: foi visto que possvel utilizar a funo scanf()
para obter valores para determinadas variveis.
4.2.3 Lendo String de Caracteres: foi mostrado como usar a funo scanf() para
ler string de caracteres que sero armazenadas em vetores.
4.2.4 Formatando a Entrada de Scanf(): neste item mostrado como formatar
scanf()de tal forma a atender as especificaes de cada programa para entrada de dados.
4.2.5 Determinando o Nmero Mximo de Caracteres a ser Lido: foi mostrado
que possvel especificar o nmero de caracteres lidos por scanf(), de tal forma a desprezar
caracteres que forem digitados a mais, por exemplo.
4.2.6 Lendo Somente Caracteres Pr-Determinados: foi visto que pode-se
previamente especificar os caracteres que sero lidos por scanf(), sendo que o caracter que
no estiver dentro destes especificados ser ignorado.

Mdulo 5 - Estruturas de Fluxo de Controle


5.1 A Declarao If
A declarao if usada quando necessrio testar em um programa duas ou mais
condies. Isto permite ao programador o desenvolvimento de programas complexos. A forma
geral da declarao if :
if (condio)
{
comandos;
}
else
{
comandos;
}

A clusula else opcional. Se condio for verdadeira (qualquer coisa diferente de 0),
o bloco que forma o destino de if ser executado; caso contrrio o bloco que forma o destino
de else ser executado (desde que exista else).
Lembre-se que somente o cdigo associado a if ou o cdigo associado a else ser
executado, nunca os dois. O destino dos dois, if e else, pode ser um comando simples ou um
bloco de comandos.
O comando if ser demonstrado atravs de um programa simples que converte bases
numricas. Este programa ser capaz de apresentar as seguintes converses:
Decimal para Hexadecimal;
Hexadecimal para Decimal.

O programa permitir que primeiro seja selecionado o tipo de converso a partir de um


menu e, ento, solicitar o nmero 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 opo: );
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);
}
}

5.1.1 - Usando a Declarao Else


possvel associar um else com qualquer if. Com esta declarao podemos acrescentar
ao teste condicional vrias opes de escolha. Se a expresso condicional associada a if
verdadeira, a instruo ou bloco de instrues associada ser executada. Se for falsa, ento a
instruo ou bloco de instrues do else ser executada. O programa seguinte demonstra este
princpio fundamental:
#include <stdio.h>
void main()

{
int i;
printf (Informe um nmero: );
scanf (%d, &i);
if (i < 0) printf (O nmero negativo);
else printf (O nmero positivo ou nulo);
}

5.1.2 O Encadeamento If-Else-If


Uma construo comum em programao o encadeamento if-else-if. O seguinte
exemplo ilustra esta construo:
if (condio)
{
comandos;
}
else if (condio)
{
comandos;
}
else if (condio)
{
comandos;
}
else
{
comandos;
}

As expresses condicionais sero avaliadas de cima para baixo. Assim que uma
condio verdadeira encontrada, o bloco associado a ela ser executado, e o resto do

encadeamento ignorado. Se nenhuma das condies for verdadeira, ento o else final ser
executado.
Se o else final no estiver presente e todas as outras condies forem falsas, ento
nenhuma ao ser realizada.
Pode-se usar o encadeamento if-else-if para implementar o programa de converso de
base numrica desenvolvido anteriormente. Na verso original, cada declarao if era avaliada
sucessivamente, mesmo se uma das declaraes anteriores tivesse xito. Ainda que no haja
grande significado neste caso, a avaliao redundante de todos os ifs no muito eficiente ou
elegante. O seguinte programa resolve este problema. Nessa verso de encadeamento if-elseif, to logo uma declarao if satisfeita, o resto das declaraes ignorado.
/* Programa de converso de base numrica 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 opo: );
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 opo escolhida invlida.)
}
}

5.1.3 A Expresso Condicional


Algumas vezes, iniciantes na linguagem C confundem-se pelo fato de que qualquer
expresso vlida na linguagem C pode ser usada para controla a declarao if. Isto , o tipo de
expresso no precisa se restringir quelas envolvendo operadores relacionais e lgicos. S
requerido que a expresso resulte em um valor zero ou no zero. Por exemplo, este programa
l dois inteiros do teclado e mostra o quociente. Para evitar um erro de diviso por zero, uma
declarao if usada para controlar o segundo nmero.
#include <stdio.h>
void main()
{
int a, b;
printf (Informe dois nmeros: );
scanf (%d%d, &a, &b);
if (b) printf (%d\n, a/b);
else printf (No posso dividir por zero\n);
}

Essa abordagem funciona porque, se b for zero, a condio controlando o if falsa e a


instruo else executada. Caso contrrio, a expresso verdadeira (no zero) e a diviso
realizada. No necessrio escrever uma declarao if como esta
if (b != 0) printf (%d\n, a/b);

porque redundante.

5.1.4 Ifs Aninhados


Um dos muitos aspectos que causam confuso na declarao if, em qualquer
linguagem de programao, so os ifs aninhados. Um if aninhado uma declarao if que
objeto de um if ou um else. Os ifs aninhados so incmodos por poderem dificultar saber qual
else est associado a qual if.

Considere este exemplo:


if (x)
if (y) printf (1);
else printf (2);

Em C, o else ligado ao if mais prximo dentro do mesmo bloco de cdigo que j no


tenha uma declarao else associada a ele. Neste caso o else associado declarao if(y).
Para fazer com que else seja associado declarao if(x), deve-se usar chaves para
sobrepor a sua associao normal, como mostrado aqui:
if (x)
{
if (y) printf (1);
}
else printf (2);

O else agora est associado ao if(x), j que ele no parte do bloco de cdigo do if(y).

5.2 A Declarao For


Uma operao que vrios programas executaro comumente repetir um conjunto de
comandos um nmero especfico de vezes. Por exemplo, pode-se querer calcular as notas dos
exames de 30 alunos ou soar trs vezes o alto-falante interno do computador. Para auxiliar
programas a repetir um ou mais comandos um certo nmero de vezes, a Linguagem C fornece
o comando for.
for(valor_inicial; condio_final; valor_incremento)

comando;

Quando um programa repetir comandos um nmero especfico de vezes, normalmente


usar uma varivel de controle, que contar o nmero de vezes que for executado os
comandos. O comando for contm quatro sees. A seo valor_inicial atribui varivel de
controle o valor inicial da varivel, que , na maioria das vezes, 0 ou 1. A seo condio_final
normalmente testa o valor da varivel de controle para determinar se o programa executou os
comandos um nmero desejado de vezes. A seo valor_incremento normalmente adiciona o
valor 1 para a varivel de controle toda a vez que os comandos so executados. Finalmente a
quarta seo do comando for o comando ou comandos especificados. O comando for
geralmente chamado de lao for. Considere o seguinte lao for, ele exibir os nmeros de 1 a
10 na sua tela:
for(contador=1; contador <= 10; contador++)
printf("%d\n", contador);

Para compreender melhor o processamento do lao for 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 lao for exibe os nmeros de 1 at 5. O segundo lao
exibe os valores de 1 at 10. O terceiro lao no exibe nenhum valor. Se for examinado com
ateno, ser visto que o programa inicialmente atribui varivel de controle do lao o valor

100. Quando o comando for testa o valor, o lao for atende imediatamente condio final,
de modo que o lao no executado.

5.2.1 Partes do Comando For so Opcionais


Como foi visto no item anterior, o lao for usa trs sees dentro do comando for: uma
inicializao, um teste e um incremento:
for(inicializao; teste; incremento)

Dependendo do programa, algumas vezes pode no ser necessrio o uso de cada


uma das sees do comando for. Por exemplo, se j foi atribuido o valor 0 varivel
conta, pode-se pular a seo de inicializao do lao. Depois, para exibir os nmeros de
0 at 999, o lao conter o seguinte:
for(; conta <1000; conta++)
printf("%d", conta);

No entanto, se for omitido uma das sees do lao for, precisa-se incluir o
ponto-e-vrgula correspondente. Por exemplo, o lao for a seguir omite as sees de
inicializao e de incremento:
for(; conta < 1000; )
printf("%d", conta++);

Da mesma forma, o comando for seguir ficar em execuo perpetuamente.


Este o chamado lao infinito:
for (; ; ; )
/*comando*/

5.2.2 Compreendendo um Lao Null


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

/* no faz nada */

Quando se coloca um lao nulo nos programas, a Linguagem C efetuar a


inicializao do lao, e, depois, repetidamente, testar e incrementar a varivel de
controle at que a varivel de controle atenda a condio final. O teste repetido do lao
consome tempo do processador, o que faz o programa retardar. Se o programa precisar
de um retardo maior, voc poder aumentar a condio final:
for(contador=1; contador <= 10000; contador++)
;

/* no faz nada */

Usar as tcnicas de retardo, tais como o lao nulo, poder causar problemas.
Primeiro, se o programa estiver rodando em um computador 286, 386 ou 486, a durao
do retardo diferir simplesmente devido diferena 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 laos "no fazem nada" consomem
tempo que o processador poderia estar gastando fazendo trabalho importante em outro
programa.

5.2.3 Compreendendo o Lao Infinito


Quando so usados laos for, precisa-se garantir que o lao atender sua condio
final. Caso contrrio, o lao continuar sua execuo para sempre. Esses laos interminveis
so chamados laos infinitos. Na maioria dos casos, os laos infinitos ocorrem como resultado
de erro na programao. Por exemplo, considere o seguinte lao:
for(i = 0; i <100; i++)
{
printf("%d", i);
resultado = valor * --i;

/*causa do erro*/

Como pode-se verificar, o segundo comando do lao decrementa o valor da


varivel de controle i. Especificamente, o lao decrementa o valor para -1, e, depois,
incrementa o valor para 0. Como resultado, o valor nunca atinge 100, de modo que o
lao no termina. Quando o programa entra em um lao infinito, pode-se pressionar
Ctrl+C para finalizar o programa.
O programa a seguir ilustra um lao infinito:
#include <stdio.h>
void main(void)
{
int i;
int result = 0;
int valor = 1;
for (i = 0; i < 100; i++)
{
printf("%d ", i);
result = valor * --i;

}
printf("Resultado %d\n", result);
}

5.2.4 Usando o operador vrgula da Linguagem C dentro de um lao for


A Linguagem C permite a declarao de mltiplas variveis do mesmo tipo separando os
nomes das variveis com vrgulas:
int idade, altura, peso;

De um modo similar, a Linguagem C permite inicializar e incrementar mltiplas


variveis em um lao for separando as operaes com vrgula. Considere o lao a
seguir, que trabalha com as variveis i e j:
for (i=0, j=100; i <= 100; i++, j++)
printf("i = %d j = %d\n", i, j);

Alguns programas iro trabalhar com mltiplas variveis em um lao for em


programas que trabalham com matrizes. O programa a seguir ilustra o uso do operador
vrgula em um lao for:
#include <stdio.h>
void main(void)
{
int i, j;
for (i = 0, j = 100; i <= 100; i++, j++)
printf("i = %d j = %d\n", i, j);
}

5.3 A Declarao While


Em
comandos

muitos

casos,

os

programas

precisam

repetir

um

ou

mais

at que o lao atenda a uma condio especfica que no envolva


necessariamente uma contagem. Por exemplo, para um programa que exiba o contedo de
um arquivo na tela, ser necessrio que o programa exiba cada linha do arquivo. Na maioria
dos casos, no sabe-se quantas linhas o arquivo contm. Portanto, no se pode usar um lao
for para exibir, por exemplo, 100 linhas. O arquivo poderia conter mais ou menos linhas. Em
vez disso, ser necessrio que o programa leia e exiba linhas at chegar ao final do arquivo.
Para fazer isso, os programas podem usar o lao while, como segue:
while (condio)

comando;

Ao encontrar um lao while no programa, a Linguagem C testa a condio especificada.


Se a condio for verdadeira, efetuar os comandos contidos no lao. Se o comando for falso,
continuar a execuo do programa ao primeiro comando que segue. Um lao while pode
repetir um nico comando ou um comando composto delimitado por abre e fecha chaves,
como segue:
while (condio)
{
/*comandos*/
}

O programa a seguir, usa o lao while para repetir um lao at que seja pressionado a
tecla S ou N em resposta a uma pergunta:
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
void main(void)
{
char letra;

/* Letra digitada pelo usurio */

printf("Quer continuar? (S/N): ");


letra = getch();

/* L a letra */

letra = toupper(letra); /* Converte letra para maiscula */


while ((letra != 'S') && (letra != 'N'))
{
putch(7);

/* Soa o alto-falante */

letra = getch();

/* L a letra */

letra = toupper(letra);
/* Converte a letra para maiscula */
}

printf("\nSua resposta foi %c\n", letra);


}

Primeiro, o programa exibir a mensagem que o primeiro comando printf contm.


Segundo, o programa usa getch para ler a tecla pressionada. Para simplificar o teste do lao, o
programa converte a letra para maiscula, de modo que o lao somente precisa testar as letras
S ou N. Terceiro, o lao while testar a letra que o usurio digitou. Se a letra for um S ou N, a
condio falhar, e os comandos do lao no sero executados. Se a letra pressionada no for
S ou N, a condio do lao ser verdadeira e seus comandos sero executados. No lao, o
comando soar o alto-falante interno do computador para indicar um caractere invlido. Em
seguida, o programa ler a nova tecla e converter a letra para maiscula. O lao depois
repetir o seu teste para determinar se o usurio digitou um S ou um N. se no, os comando
do lao sero repetidos. Caso contrrio, a execuo do programa continuar no primeiro
comando que segue o lao.

5.3.1 Compreendendo as Partes de um Lao While


Foi visto anteriormente que um lao for realmente contm quatro sees: uma
inicializao, um teste, um comando de execuo e um incremento. Por outro lado, um lao
while contm somente um teste e os comandos que quer-se repetir, como visto no item
anterior.
Foi visto tambm, que um lao infinito aquele cuja condio final nunca atendida, e
portanto o lao continua a execuo para sempre. Ao escrever programas que usa laos while,
pode-se reduzir a possibilidade de um lao infinito garantindo que seus laos while efetuem os
mesmos passos executados por um lao for. Veja a seguir os quatro passos relacionados na
tabela:
Ao
Inicializa
Testa
Executa
Modifica

Descrio
Inicializa a varivel de controle do lao
Testa a varivel de controle ou a condio do lao
Executa os comando desejados no lao
Modifica o valor da varivel de controle ou efetua uma operao que
afetar a condio que voc est testando

Ao contrrio do lao for, que permite explicitamente inicializar e incrementar uma


varivel de controle, um lao while requer que sejam inclusos comandos no programa que
efetuem esses passos. O programa a seguir, ilustra como o programa efetua esses quatro
passos. Ao contrrio dos programas escritos anteriormente, este usa um lao while para exibir
os nmeros de 1 a 100:
#include <stdio.h>
void main(void)
{
int contador = 1;

/* Inicializa a varivel de controle */

while (contador <= 100)

/* Testa a varivel de controle */

{
printf("%d ", contador);
contador++;

/* Executa os comandos */

/* Modifica a varivel de controle */

}
}

5.4 A Declarao Do-While


Ao contrrio dos laos for e while, que testam a condio do lao no incio, o lao dowhile verifica sua condio no final do lao. Isso significa que um lao do-while ser executado
pelo menos uma vez. A forma geral do lao do-while :
do{
comandos;
}while(condio);

Ainda que as chaves no sejam necessrias quando somente um comando ser


executado no lao, elas so usadas para aumentar a legibilidade do cdigo do programa. Este
programa usa um lao do-while para ler nmeros do teclado at que um deles seja menos que
100.
#include <stdio.h>
void main()
{
int num;
do
{
scanf (%d, &num);
}
while(num > 100);
}

Talvez o uso mais comum do lao do-while seja em uma rotina de seleo em menu. J
que sempre ser preciso de uma rotina de seleo em menu para ser executada no mnimo

uma vez, o lao do-while uma opo bvia. O seguinte fragmento mostra como adicionar um
lao do-while no menu do programa de converso numrica.
/* Assegura que o usurio especificou uma opo vlida */
do
{
printf (Converte:\n);
printf ( 1: decimal para hexadecimal\n);
printf ( 2: hexadecimal para decimal\n);
printf (informe sua opo: );
scanf (%d, &opcao);
}while(opcao < 1 || opcao > 2);

Depois que a opo tiver sido apresentada, o programa se repetir at que uma
opo vlida seja selecionada.

5.5 Compreendendo o Comando Continue


Dependendo do propsito do programa, algumas vezes, com base em uma segunda
condio especfica, poder ser necessrio que o programa pule a iterao atual. O
comando continue da Linguagem C lhe permite fazer exatamente isso. Se a Linguagem
C encontrar um comando continue em um lao for, a Linguagem C automaticamente
executar a poro de incremento do lao, e, depois, efetuar o teste da condio final.
Se a Linguagem C encontrar um comando continue em um lao while ou do, ento a
Linguagem C imediatamente efetuar o teste da condio final. Para compreender
melhor o comando continue, considere o seguinte programa, que usa continue em um
lao for e um lao while para exibir os nmeros pares e mpares entre 1 e 100:
#include <stdio.h>
void main(void)
{
int contador;
printf("\nValores pares\n");
for (contador = 1; contador <= 100; contador++)
{
if (contador % 2)

/* mpar */

continue;
printf("%d ", contador);
}
printf("\nValores mpares\n");
contador = 0;
while (contador <= 100)
{
contador++;
if (! (contador % 2)) /* Par */
continue;
printf("%d ", contador);
}
}

importante observar que normalmente pode-se eliminar a necessidade de usar um


comando continue reprojetando o uso dos comandos if e else em seu programa. Por
exemplo, o programa a seguir tambm exibe valores pares e mpares sem usar continue:
#include <stdio.h>
void main(void)
{
int contador;
printf("\nValores pares\n");
for (contador = 1; contador <= 100; contador++)
{
if (!(contador % 2))

/* Par */

printf("%d ", contador);


}
printf("\nValores mpares\n");

contador = 0;
while (contador <= 100)
{
contador++;
if (contador % 2) /* mpar */
printf("%d ", contador);
}
}

5.6 Finalizando um Lao Usando o Comando Break


Dependendo do propsito do programa, algumas vezes, com base em uma segunda
condio especfica, poder querer que o lao termine automaticamente, com seu programa
continuando seu processamento no comando que segue o lao. O comando break lhe permite
fazer exatamente isso. Quando a Linguagem C encontra um break em um lao, a execuo do
lao terminar de imediato. O prximo comando que o programa executa o comando que
segue imediatamente o lao. No caso de um comando for, a Linguagem C no efetuar a seo
de incremento do lao, ao invs disso, o lao termina imediatamente. O programa a seguir
ilustra o uso do comando break. O programa percorre os nmeros de 1 a 100, e, depois, de
100 a 1. Toda vez que o lao chega ao valor 50, o comando break termina imediatamente o
lao:
#include <stdio.h>
void main(void)
{
int contador;
for (contador = 1; contador <= 100; contador++)
{
if (contador == 50)
break;
printf("%d ", contador);
}
printf("\nPrximo lao\n");

for (contador = 100; contador >= 1; contador--)


{
if (contador == 50)
break;
printf("%d ", contador);
}
}

5.7 Desvios com o comando goto


Como a maioria das linguagens de programao, a Linguagem C fornece um comando
goto, que permite que a execuo do programa desvie-se para uma localizao especfica,
chamada rtulo. O formato do comando goto como segue:
goto rotulo;
rotulo:

O programa a seguir usa o comando goto para exibir os nmeros de 1 a 100:


#include <stdio.h>
void main(void)
{
int conta = 1;
rotulo:
printf("%d ", conta++);
if (conta <= 100)
goto rotulo;
}

Quando usa-se o comando goto, o rtulo precisa residir na funo atual. Em outras
palavras, no pode-se usar goto para desviar-se de main para um rtulo que aparece em
outra funo e vice - versa.

5.8 A Declarao Switch


Ainda que o encadeamento if-else-if possa realizar testes de mltipla escolha, ele
quase nunca elegante. O cdigo pode ser muito difcil de acompanhar e pode confundir at

mesmo o seu autor. Por esse motivo, a linguagem C tem internamente uma declarao de
deciso de mltipla escolha chamada de switch. Na declarao switch, a varivel
sucessivamente testada contra uma lista de inteiros ou constantes caractere. Quando uma
associao encontrada, o conjunto de comandos associado com a constante executado.
As constantes no precisam sequer estar em qualquer ordem especial. A forma geral
da declarao switch :
switch (varivel)
{
case constante1:
commandos;
break;
case constante2:
commandos;
break;
case constante3:
commandos;
break;
M
default
commandos;
}

Onde a declarao default executada se nenhuma correspondncia for encontrada.


O default opcional e, se ele no estiver presente, nenhuma ao ser realizada se todas as
correspondncias falharem. Quando uma correspondncia encontrada, os comandos
associados a case so executados at que o break seja encontrado ou at que se encontre o
final do switch.
H trs coisas importantes a saber sobre a declarao switch:
1) Ele difere do if, j que o switch pode testar somente igualdades, enquanto a
expresso condicional if pode ser de qualquer tipo;
2) Nunca duas constantes case no mesmo switch podem ter valores iguais.
Obviamente, uma declarao switch dentro de outra declarao switch pode ter as mesmas
constantes case;

3) Uma declarao switch mais eficiente que um encadeamento if-else-if.


possvel especificar comandos no switch que sero executados caso nenhuma
correspondncia seja encontrada. Basta adicionar uma declarao default. A declarao
default uma boa maneira de direcionar qualquer final livre que possa ficar pendente na
declarao switch. Por exemplo, no programa de converso de base numrica, pode-se usar
uma declarao default para informar ao usurio que uma resposta invlida foi dada e para
tentar outra vez.
Usa-se freqentemente o switch para desviar uma seleo de menu para a rotina
apropriada. Seguindo essa linha, pode-se us-la para fazer um melhoramento adicional ao
programa de converso de base numrica. A verso mostrada aqui elimina as sries anteriores
de ifs e substitui-as por uma clara declarao switch.
/* Programa de converso de base numrica switch
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 opo: );
scanf (%d, &opcao);
switch(opcao)
{
case 1:
printf (\nInforme o valor em decimal: );
scanf (%d, &valor);

printf (%d em hexadecimal e: %x, valor, valor);


break;
case 2:
printf (\nInforme o valor em hexadecimal: );
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
break;
default:
printf (\nOpo invlida. Tente outra vez.)
}
}

5.8.1 As Declaraes Switch Aninhadas


possvel ter um switch como parte da seqncia de declarao de um switch
externo. Mesmo que as constantes case do switch interno e externo contenham valores
comuns, nenhum conflito surgir. Por exemplo, o seguinte fragmento de cdigo
perfeitamente aceitvel.
switch(x){
case 1:

switch(y){

case 0:
printf (erro de diviso por zero);
break;
case 1:
process (x, y);

}
break;
case 2:
.
.
.

Como outro exemplo, um programa de banco de dados bastante simples mostrado a


seguir ilustra como se pode usar uma declarao switch aninhada. Este programa solicita ao
usurio a regio e a letra inicial do nome do vendedor e, ento, mostra o demonstrativo de
vendas do mesmo. Switchs aninhados so requeridos uma vez que muitos vendedores tm a
mesma letra inicial. Note que uma nova funo, toupper( ), introduzida. Ela retorna a letra
maiscula correspondente do seu argumento caractere. Ela usada neste programa para
permitir que o usurio insira informaes tanto em letra maiscula como em letra minscula.
A funo complementar de toupper( ) tolower( ), que converte caracteres maisculos em
minsculos. Ambas as funes esto contidas na biblioteca ctype.h.
/* Um banco de dados simples de vendedores por regio */
#include <stdio.h>
#include <ctype.h>
void main()
{
char regiao, vendedor;
printf (As regies so: Leste, Oeste e Norte\n);
printf (Informe a primeira letra da regio: );
regiao = getche();
regiao = toupper(regiao); /*converte para maisculas*/
printf (\n);
switch (regiao)
{
case L:
printf (Vendedores so: Rafael, Joo e Maria \n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{

case R:
printf (Vendas: R$%d\n, 10000);
break;
case J:
printf (Vendas: R$%d\n, 12000);
break;
case M:
printf (Vendas: R$%d\n, 14000);
}
break;
case O:
printf (Vendedores so: Ronaldo, Lisa e Hilton\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 10000);
break;
case L:
printf (Vendas: R$%d\n, 9500);
break;
case H:
printf (Vendas: R$%d\n, 13000);

}
break;
case N:
printf (Vendedores so: Toms, Joo e Raquel\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 5000);
break;
case J:
printf (Vendas: R$%d\n, 9000);
break;
case T:
printf (Vendas: R$%d\n, 14000);
}
break;
}
}

Para ver como o programa funciona, seleciona-se a regio Oeste, digitando O. Isso
indica que case O selecionado pela declarao switch externa. Para ver o total de vendas de
Hilton, digite H. Isso faz com que o valor 13000 seja apresentado.
Note que a declarao break em um switch aninhado no tem efeito no switch
externo.

5.9 Laos Aninhados

Quando um lao est dentro de outro, diz-se que o lao mais interno aninhado.
Laos aninhados propiciam o meio de resolver alguns problemas interessantes de
programao. Por exemplo, este pequeno programa exibe as quatro primeiras potncias dos
nmeros de 1 a 9.
/* Exibe uma tabela das 4 primeiras potencies de 1 a 9 */
#include <stdio.h>
void main()
{
int i, j, k, temp;
printf( i i^2 i^3 i^4\n);
for (i = 1; i < 10; i++)
{ /* lao externo */
for (j = 1; j < 5; j++)
{ /* primeiro aninhamento */
temp = 1;
for (k = 0; k < j; k++) /* segundo aninhamento */
temp = temp * i;
printf (%9d, temp);
}
printf (\n);
}
}

Algumas vezes, importante determinar quantas interaes o lao interno


executa. Este nmero conseguido multiplicando-se o nmero de vezes que o lao
externo intera pelo nmero de vezes que o lao interno repetido cada vez que
executado. No exemplo do programa de potncia, o lao externo repetido nove vezes e
o segundo lao, quatro vezes; assim, o segundo lao interagir 36 vezes. O lao interno
executado, em mdia, duas vezes; dessa forma, o nmero total de interaes 72.
Como no ltimo exemplo, um melhoramento final para o programa de converso
de base numrica usando-se laos aninhados mostrado aqui. O lao externo faz com
que o programa seja executado at que o usurio diga para parar. O lao interno
assegura que o usurio informar uma seleo vlida do menu. Agora, em vez de

simplesmente converter um nmero toda vez que for executado, o programa repete at
que o usurio queira parar.
/* Programa de converso de base numrica verso final
decimal ---> hexadecimal
hexadecimal ---> decimal*/
#include <stdio.h>
void main()
{
int opcao;
int valor;
/*repete at que o usurio diga para terminar*/
do
{
/*assegura que o usurio especificou uma opo vlida*/
do
{
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (3: fim\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
}
while(opcao < 1 || opcao > 3);
switch(opcao)
{

case 1:
printf (\nInforme o valor em decimal: )
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
break;
case 2:
printf (\nInforme o valor em hexadecimal: )
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
break;
case 3:
default:
printf (\nOpo invlida. Tente outra vez.)
}
printf (\n);
}
while(opcao != 5);
}

5.10 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
5.1 A Declarao If: neste item foi apresentada uma introduo da declarao if,
listando suas caractersticas e propriedades bem como sua estrutura. Foi apresentado um
exemplo com o uso da declarao if para facilitar o entendimento e compreenso.
5.1.1 Usando a Declarao Else: foi apresentada a declarao else, que tem como
funo dar seqncia s opes apresentadas pela declarao if.
5.1.2 O Encadeamento If-Else-If: foi mostrado o encadeamento de ifs e elses que
permite inserir dentro das alternativas um primeiro if novos teste condicionais.

5.1.3 A Expresso Condicional: foi visto que qualquer expresso vlida na


linguagem C pode ser usada para controla a declarao if. Isto , o tipo de expresso no
precisa se restringir quelas envolvendo operadores relacionais e lgicos. S requerido que a
expresso resulte em um valor zero ou no zero.
5.1.4 Ifs Aninhados: foi visto que um if aninhado uma declarao if que
objeto de um if ou um else, ou seja, uma declarao if dentro da outra.
5.2 A Declarao For: neste item foi apresentada uma introduo da declarao
for, listando suas caractersticas e propriedades bem como sua estrutura. Foi apresentado que
a declarao for usada para repetir um ou mais comandos um certo nmero de vezes.
5.2.1 Partes do Comando For so Opcionais: foi visto que muitas partes
constituintes da declarao for so opcionais.
5.2.2 Compreendendo um Lao Null: foi visto que este um recurso para obter
um retardo ou uma breve pausa durante a execuo de um programa.
5.2.3 Compreendendo o Lao Infinito: foi visto que muitas vezes, devido erros
de programao, alguns laos for nunca atingem sua condio final, sendo executados
infinitamente.
5.2.4 Usando o operador vrgula da Linguagem C dentro de um lao for: foi
mostrado que a Linguagem C permite inicializar e incrementar mltiplas variveis em um lao
for separando as operaes com vrgula.
5.3 A Declarao While: foi visto que ao encontrar um lao while no programa, a
Linguagem C testa a condio especificada. Se a condio for verdadeira, efetuar os
comandos contidos no lao. Se o comando for falso, continuar a execuo de seu programa
ao primeiro comando que segue.
5.3.1 Compreendendo as Partes de um Lao While: foi estudado as partes
componentes do lao while, de tal forma a conhece-las evitando laos infinitos e erros de
programao.
5.4 A Declarao Do-While: neste item foi mostrado que o lao do-while verifica
sua condio no final do lao. Isso significa que um lao do-while ser executado pelo menos
uma vez.
5.5 Compreendendo o Comando Continue: foi visto neste item que o comando
continue em um programa utilizado quando quer-se pular a iterao atual.
5.6 Finalizando um Lao Usando o Comando Break: o comando Break utilizado
para terminar imediatamente a execuo de um lao e a partir da continuar executando a
prxima linha de cdigo aps o lao.
5.7 Desvios com o comando goto: o comando goto permite que a execuo do
programa desvie-se para uma localizao especfica, chamada rtulo.
5.8 A Declarao Switch: na declarao switch, a varivel sucessivamente
testada contra uma lista de inteiros ou constantes caractere. Quando uma associao
encontrada, o conjunto de comandos associado com a constante executado.

5.8.1 As Declaraes Switch Aninhadas: da mesma forma vista para a declarao


for, a declarao switch pode ser posta no cdigo de programao da forma aninhada.
5.9 Laos Aninhados: Quando um lao est dentro de outro, diz-se que o lao
mais interno aninhado. Laos aninhados propiciam o meio de resolver alguns problemas
interessantes de programao.

Funes

Objetivos
No primeiro captulo foi dito que um programa em C pode ser composto de uma ou
mais funes, sendo que a nica obrigatria main(). Agora, estudaremos como utilizar
outras funes em nossos programas.

Pr-requisitos
Para um melhor aprendizado necessrio que o leitor tenha acompanhado o artigo
anterior, pois os artigos obedecem a uma seqncia.

Nota: Este artigo faz parte do curso de Linguagem C Bsico.

Funes
As funes so blocos de instrues que facilitam o entendimento do cdigo. Sua
sintaxe :

Tipo_da_funo nome_da_funo (tipo var1, tipo var2,...,tipo varN)


{

corpo da funo
}

O tipo da funo pode ser qualquer um dos mostrados at agora e representa o tipo do
dado que retornado pela funo. Caso a funo no retorne nenhum valor dizemos que
ela do tipo void. E caso no seja especificado nenhum tipo, por padro a funo
retorna um inteiro. Mas importante lembrar que sempre se deve declarar o tipo da
funo garantindo assim maior portabilidade. Entre parnteses esto os parmetros da
funo que constitudo pelos nomes das variveis que se deseja passar para funo
separados por virgulas e acompanhados de seus respectivos tipos, como mostra a
sintaxe acima. No caso da funo no conter parmetros a lista de parmetros ser
vazia, mas mesmo assim ser necessrio utilizar os parnteses. No corpo da funo vem
o cdigo em C, este cdigo privativo da funo, ou seja, nenhuma outra funo poder
acessa-la com nenhum comando, exceto por meio de uma chamada a funo. Isso quer
dizer que o cdigo da funo no pode afetar outras partes do programa, a menos que
sejam utilizadas variveis Globais. Isto porque as variveis contidas em uma funo so
locais, s existem naquela funo. Essas variveis so criadas quando entram na funo
e destrudas ao sair.

Para entender melhor o uso de funes veja o exemplo abaixo. Este programa calcula o
fatorial de um nmero qualquer.

No programa acima temos a funo main() que obrigatria em qualquer programa,


nela pedimos para que o usurio digite o nmero que se deseja calcular o fatorial.
Depois chamamos a funo CalculaFatorial passando para ela o argumento Num.
necessrio que o tipo dos argumentos (Num) usados para chamar a funo seja
compatveis com o tipo de seus parmetros (x). Caso contrario poder ocorrer erros. Ao
chamar a funo que calcula o fatorial o valor do argumento contido na varivel Num

copiado para o parmetro x da funo CalculaFatorial e qualquer modificao no seu


valor feito apenas na varivel local x, no alterando o valor da varivel usada na
chamada.

O comando return usado no final da funo o responsvel por retornar um valor para
a instruo que o chamou, neste caso para a varivel Fatorial. Que por sua vez
impressa na tela.

Atravs do prottipo usado no inicio do programa possvel que o compilador verifique


se existem erros nos tipos de dados entre os argumentos usados para chamar uma
funo e a definio de seus parmetros. Alm de verificar se a quantidade de
argumentos igual a quantidade de parmetros, caso contrario causar erros na
execuo do programa. A sintaxe para definir o prottipo de uma funo dada por:

tipo Nome_Da_Funo(tipo parametro1, tipo parametro2,..., tipo parametroN);

Caso a funo no utilize nenhum parmetro deve-se utilizar o void. Dessa forma
teramos:

tipo Nome_Da_Funo(void);

importante lembrar que antes que a funo seja usada pela primeira vez necessrio
que ela seja declarada. Isso ocorre devido o compilador C (em sua grande maioria) por
padro assume que uma funo devolve um valor inteiro. Portanto se alguma funo
devolver um tipo diferente de inteiro o compilador gera um cdigo errado para chamla. Por esse motivo que importante declarar o tipo que a funo retorna no inicio do
programa e isso pode ser feito utilizando os prottipos. Alm dos prottipos existe um
outro mtodo que era muito usado quando a linguagem C foi inventa, no entanto hoje
ela considerada obsoleta. Porm existem alguns programas que ainda usa este mtodo
obsoleto, dessa forma sua declarao seria:

tipo Nome_Da_Funo();

A diferena deste mtodo para o do prottipo que neste mesmo que a funo tenha
argumentos no preciso de declara-los. Na verdade o prottipo uma extenso deste
mtodo.

Veja um outro exemplo de programa que utiliza funo:

Neste ultimo programa, temos uma funo que tem como parmetros os coeficientes de
uma equao do tipo:
. Esta funo verifica se a for igual a zero
identificando assim a equao como sendo do 2 Grau e posteriormente se delta maior
ou igual a zero, caso seja a equao ser resolvido pela formula de baskara. Caso delta
seja menor que zero ser impresso a seguinte mensagem: No foi possvel calcular x1 e
x2, pois so nmeros imaginrios. Se a diferente de zero a equao ser do 1 grau,
ento verifica se b igual a zero, caso seja no ter soluo, pois no pode haver diviso
por zero. A funo CalculaEquacao do tipo void pois no retorna nenhum valor para
funo main(). Exatamente por esse motivo a funo principal apenas chama a
CalculaEquacao. A biblioteca math.h foi inserida pela diretiva include, ou seja, a
linha #include <math.h> foi inserida no programa para que as funes pow() e sqrt()
pudessem ser utilizadas. A funo pow() calcula a base elevada uma potencia. J a
funo sqrt() calcula a raiz quadrada de um nmero. Estas e outras funes pertencentes
biblioteca math.h sero descritas e estudas com mais detalhes no decorrer deste
tutorial.

No exemplo anterior no foi utilizada a funo return, pois nenhum valor necessitou ser
devolvido. Neste caso o programa retorna funo que a chamou quando o ultimo
comando (}) da funo CalculaEquacao for encontrado. claro que a chave no estar
no cdigo-objeto do programa, mas pode-se imaginar como se estivesse. O cdigoobjeto nada mais do que o cdigo contendo as instrues traduzidas para a linguagem
de maquina.

Concluso
Neste artigo vimos como utilizar funes em nossos programas, facilitando assim o
entendimento do cdigo. Atravs desse estudo conclui-se que as funes devem
obedecer sintaxe apresentada neste trabalho onde deve ser definidos o tipo de dado
que a funo retorna, os parmetros e os seus respectivos tipos. Os tipos dos argumentos
e dos parmetros das funes devem ser compatveis. Do mesmo modo a quantidade de
argumentos deve ser igual as dos parmetros. Para que a funo retorne um valor
utiliza-se return. Foi visto tambm que as funes devem ser declaradas antes de serem
chamadas e isto pode ser feito utilizando os prottipos de funes. Lembre-se que o
compilador C por padro define que toda funo retorna um valor inteiro, portanto
necessrio muito cuidado caso a funo retorne um tipo diferente de inteiro. Todas essas
informaes foram apresentadas atravs de exemplos simples e prticos. Com isso
verifica-se que o uso de funes em nossos programas so indispensveis.

Mdulo 3 Funes na Linguagem C


3.1 Funes
A maioria dos programas apresentam a funo main. Quando os programas tornam-se
maiores e mais complexos, pode-se melhorar a clareza e compreenso do trabalho dividindo-o
em partes menores, chamadas funes. Vamos citar o exemplo de um determinado programa,
suponha um programa de contabilidade. Poderia haver no programa uma funo que
efetuasse as operaes normais de um contador, uma funo diferentes para contas a pagar,
uma terceira para contas a receber e uma quarta para gerar um balano. Se fossem colocados
todos os comandos do programa dentro da funo main, o programa ficaria muito grande, e
seria difcil de compreende-lo. medida que o tamanho e a complexidade do programa
aumentam, aumenta tambm a possibilidade de erros. Se o programa for dividido em blocos
menores e mais facilmente gerenciveis, poder evitar erros. Uma funo uma coleo
nomeada de comandos que efetuam uma tarefa especfica. Por exemplo, a funo ola_mundo,
usa a funo printf para exibir uma mensagem:
void ola_mundo (void)
{
printf(Ol mundo!\n);
}

A palavra chave void diz a Linguagem C que a funo no retorna um valor. Em muitos
casos, as funes usaro return para retornar o valor de um clculo para a funo chamadora.
Se a funo no usa return para retornar um resultado, deve-se preceder o nome da funo
com void. O void que aparece nos parmetros diz que a funo no usa parmetros. Um
parmetro a informao que o programa passa para a funo. Por exemplo, quando os
programas chamam printf, as informaes que se especifica dentro dos parnteses so
parmetros. Quando uma funo no usa parmetros, deve-se colocar void dentro dos
parnteses. Para usar uma funo, especifica-se o nome da funo seguido de parnteses. Os
programadores referenciam o uso de uma funo como uma chamada da funo. O programa
a seguir, usa a funo oi_pessoal:
#include <stdio.h>
void ola_pessoal(void)
{
printf("Ol
}

pessoal!\n");

void main(void)
{
ola_pessoal();
}

Ao executar esse programa, a funo main executada primeiro. Como se pode


ver, o nico comando em main a chamada da funo oi_pessoal. Quando C encontra a
chamada da funo, imediatamente transfere a execuo do programa para a funo,
iniciando a execuo do programa com o primeiro comando da funo. Depois que o
ltimo comando da funo termina, a Linguagem C transfere a execuo para o
comando que segue imediatamente a chamada da funo.
Para compreender melhor esse processo, mude a funo main dentro do
programa anterior como mostrado aqui:
void main(void)
{
printf(Prestes chamar a funo\n);
oi_pessoal();
printf(Voltei da chamada da funo\n);
}

3.2 Variveis dentro das Funes


medida que as funes vo se tornando mais teis nos programas, muitas delas
requerem que as variveis gerem resultados valiosos. Para usar uma varivel dentro de uma
funo, precisa-se primeiro declarar a varivel, exatamente como feito em main.
Por exemplo, o programa a seguir chama a funo trs_olas, que usa a varivel
contador em um lao for para exibir uma mensagem 3 vezes:
#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();
}

Quando se declara variveis dentro de uma funo, os nomes usados para essas
variveis so exclusivos para a funo.
Portanto, se o programa usa dez funes diferentes e cada funo usa uma varivel
chamada contador, a Linguagem C considera a varivel de cada funo como distinta. Se uma
funo requer muitas variveis, elas devero ser declaradas no incio da funo, exatamente
como se faria dentro de main.

3.3 Main como uma Funo


Quando um programa criado, usa-se o nome da funo main para determinar o
primeiro comando que o programa executar. Na verdade, main uma funo, de modo que,
caso tenha perguntas sobre os tipos de operaes que podem ser executadas dentro das
funes, a regra bem simples: tudo o que se pode fazer em main, pode-se fazer em uma
funo. Exatamente como pode declarar variveis em main, tambm pode declarar variveis
nas funes. Tambm possvel utilizar construes tais como if, while, e for em suas funes.
Finalmente, uma funo pode chamar (usar) outra. Por exemplo, o programa a seguir usa duas
funes. Quando o programa inicia, main chama a funo tres_olas, que, por sua vez, chama a
funo oi_pessoal trs vezes para exibir mensagens na tela, como mostrado aqui:
#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();
}

3.4 Introduo aos Parmetros


Um parmetro um valor passado a uma funo. A maioria dos programas
apresentados passou parmetros para a funo printf. medida que o uso de funes for
maior, poder passar parmetros para as funes de modo a torn-las mais teis. Por
exemplo, considere a seguinte construo da funo tres_olas, que chama a funo oi_pessoal
trs vezes:
void tres_olas(void)
{
int contador;
for (contador = 1; contador <= 3; contador++)
ola_pessoal();
}

Uma funo mais til permite especificar, como um parmetro, o nmero de vezes que
quer que o programa exiba a mensagem. Para usar um parmetro, a funo precisa
especificar o nome e o tipo do parmetro, como mostrado aqui:
void ola_conta(int msg_conta)

Neste caso, a funo ola_conta suporta um parmetro do tipo int chamado


msg_conta. Quando outra funo, tal como main, quiser usar ola_conta, a funo precisa
especificar o valor que a Linguagem C atribui para o parmetro msg_conta:
ola_conta(2);
ola_conta(100);
ola_conta(1);

/*Exibe a mensagem 2 vezes*/


/*Exibe a mensagem 100 vezes*/
/*Exibe a mensagem uma vez*/

O programa a seguir ilustra como pode usar uma funo com um parmetro:

#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);
}

3.5 Parmetros Mltiplos


Em geral, pode-se passar um nmero irrestrito de parmetros para uma funo. No
entanto, as pesquisas mostram que, quando o nmero de parmetros excede sete, a
funo mostra-se mais difcil de se compreender e usar corretamente, ficando, portanto,
mais susceptvel a erros. Quando a funo usa mais de um parmetro, precisa
especificar o tipo e o nome de cada parmetro e separar os parmetros por vrgulas,
como mostrado aqui:
void uma_funcao(int idade, float sal, int num_cargo)
{

/*Comandos da funo*/
}

Quando o programa chamar a funo, ser necessrio especificar valores para cada
parmetro, como mostrado aqui:
uma_funcao(33, 40000.00, 534);

3.6 Retornando um Valor de uma Funo


Funes mais complexas normalmente realizam clculos e retornam resultados. Pra
fornecer um resultado ao chamador, uma funo precisar usar o comando return que ser
implementado como segue:
return (resultado);

O tipo de valor que a funo retorna (int, float, char, etc.) determina o tipo da funo.
Por exemplo, se uma funo retorna um valor do tipo int, necessrio preceder o nome da
funo com o nome do tipo, como mostrado aqui:
int uma_funo(int valor)
{
/*Comandos da funo*/
}

A funo a seguir, retorna o cubo do valor inteiro que o programa especifica


como seu parmetro. Por exemplo, se o chamador passar o valor 5 para a funo, a
funo retornar o valor 5*5*5, ou 125:
int i_cubo(int valor)
{
return (valor *valor *valor);
}

Como visto, a funo usa o comando return para retornar o resultado do clculo ao
chamador. O cdigo dentro da funo de chamada pode atribuir o resultado da funo
chamada (tambm conhecido como valor de retorno) a uma varivel, ou o cdigo pode usar o
valor de retorno dentro de uma terceira funo, tal como printf, como mostrado aqui:
result = i_cubo(5);
printf(O cubo de 5 %d\n, I_cubo(5));

O programa a seguir usa a funo i_cubo para determinar vrios valores diferentes ao
cubo:

#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));
}

Os valores que so passados para uma funo precisam corresponder aos tipos de
parmetros contidos dentro da declarao dessa funo. Por exemplo, se quiser
determinar o cubo de um valor em ponto flutuante, crie uma segunda funo chamada
f_cubo, como mostrado a seguir (observe que o valor de retorno tambm do tipo
float):
float f_cubo(float valor)
{
return (valor *valor *valor);
}

3.7 Comando Return


Quando a Linguagem C encontra um comando return em uma funo, ela finaliza
imediatamente a execuo da funo e retorna o valor especificado para o chamador. O
programa no executa quaisquer outros comandos dentro da funo aps o comando return.
Em vez disso, ele continua a execuo da funo chamadora.
Outros programas possuem funes que contm mltiplos comandos return, cada um
dos quais retornando um valor para uma condio especfica. Por exemplo, considere a funo
compara_valores, mostrada a seguir:
int compara_valores(int primeiro, int segundo)

{
if (primeiro == segundo)
return (0);
else if (primeiro > segundo)
return (1);
else if (primeiro < segundo)
return (2);
}

A funo compara_valores examina dois valores listados na tabela abaixo:


Resultado
0
1
2

Significado
Os valores so iguais
O primeiro valor maior que o segundo
O segundo valor maior que o primeiro

Como regra, deve-se tentar limitar as funes a usar somente um comando return.
medida que as funes se tornarem maiores e mais complexas, ter muitos comandos return
normalmente tornar as funes mais difceis de compreender. Na maioria dos casos, pode-se
reescrever a funo para que ela use somente um comando return, como mostrado aqui:
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 funo simples, pode-se ter dificuldades em compreender


qual a vantagem de usar um nico comando de return. No entanto, medida que as

funes se tornarem mais complexas, a vantagem ficar mais clara. Pode-se observar
que, algumas vezes, usar mais de um comando return produz um cdigo mais legvel do
que a alternativa de um nico return. Deve-se escrever o cdigo mais legvel e
facilmente modificvel quanto possvel; se usar mltiplos return atingir os objetivos
pr-estabelecidos, ento utilize quantos comandos return forem necessrios.

3.8 Prottipos de Funo


A maioria dos novos compiladores C precisa conhecer os tipos de retorno e de
parmetro de uma funo antes do programa chamar a funo.Colocando as funes antes
dos seus chamadores dentro do cdigo do seu programa, permitir que o compilador C
conhea as informaes que ele dever ter antes de encontrar a chamada da funo. No
entanto, medida que os programas ficam mais complexos, pode se tornar impossvel colocar
as funes sempre na ordem correta. Portanto, a Linguagem C permite colocar prottipos de
funo no seu programa, para descrever os tipos de parmetro e de retorno de uma funo.
Por exemplo, considere um programa que use as funes i_cubo e f_cubo. Antes que a funo
seja usada pela primeira vez, o programa pode incluir um prottipo semelhante ao seguinte:
int i_cubo(int);

/*Retorna um parmetro int*/

float f_cubo(float);

/* Retorna um parmetro float*/

Como pode-se ver, o prottipo da funo especifica os tipos de parmetro e de


retorno da funo. O programa a seguir usa dois prottipos de funo para eliminar a
necessidade de ordem da funo:
#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);
}

3.9 Biblioteca de Execuo


Muitas vezes, uma funo criada para um determinado programa atende as
necessidades de um segundo programa. A capacidade de reutilizar as funes em mais de um
programa pode poupar um tempo considervel de programao e teste. Para isto s copiar a
funo de um para outro programa.
Antes de gastar um tempo enorme desenvolvendo uma ampla variedade de funes
de propsito geral, no deixe de examinar as funes que seu compilador fornece. Muitos
compiladores referenciam essas funes internas como biblioteca de execuo. A maioria dos
compiladores fornece centenas de funes de biblioteca de execuo com propsito que vo
de abertura e trabalho com arquivos para acessar informaes do disco ou de diretrio para
determinar o tamanho de uma string de caracteres. As duas ou trs horas que sero gastas
para ler a documentao da biblioteca de execuo pouparo muitas horas de programao.

3.10 Funes que no retornam Int


Muitas funes retornam valores do tipo int. Quando uma determinada funo no
retorna um valor do tipo int (em vez disso ela pode retornar float, double, char, etc.) precisase informar ao compilador o tipo de retorno da funo. O programa a seguir usa a funo
valor_medio para determinar a mdia de trs valores do tipo int. A funo retorna a mdia
usando um valor do tipo float (repare que o cabealho da funo especifica o tipo de retorno
da funo):
#include <stdio.h>
float valor_medio(int a, int b, int c)
{
return ((a + b + c) / 3.0);
}
void main(void)
{

printf("A mdia de 100, 133 e 155 %f\n",


valor_medio(100, 133, 155));
}

3.11 Variveis Locais


A Linguagem C permite declarar variveis dentro de suas funes. Essas variveis so
chamadas de variveis locais, pois seus nomes e valores somente tm significado dentro da
funo que contm a declarao da varivel. O programa a seguir ilustra o conceito de uma
varivel local. A funo valores_locais declara 3 variveis a, b e c, e atribui s variveis os
valores 1, 2 e 3, respectivamente. A funo main tenta imprimir o valor de cada varivel. No
entanto, como os nomes dos valores so locais funo, o compilador gera erros, dizendo que
os smbolos a, b, e c esto indefinidos.
#include <stdio.h>
void valores_locais(void)
{
int a=1, b=2, c=3;
printf("a contm %d b contm %d c contm %d\n", a,b,c);
}
void main(void)
{
printf("a contm %d b contm %d c contm %d\n", a,b,c);
}

3.12 - Sobrecarga da Funo


Quando um programa usa uma funo, a Linguagem C armazena o endereo de
retorno, os parmetros e as variveis locais na pilha. Quando a funo termina, a Linguagem C
descarta o espao da pilha que continha as variveis locais e parmetros, e, depois, usa o valor
de retorno para retornar a execuo do programa para a posio correta.

Embora o uso da pilha seja poderoso porque permite que o programa chame e passe as
informaes para as funes, tambm consome tempo de processamento. Os
programadores chamam a quantidade de tempo que o computador requer para colocar e
retirar informaes da pilha de sobrecarga da funo. Para compreender melhor o
impacto da sobrecarga da funo no desempenho do seu programa, considere o
programa a seguir. Primeiro o programa usa um lao para somar os valores de 1 a

100.000. Em seguida, repete um lao novamente, mas usa uma funo para somar os
valores, como mostrado aqui:
#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 lao %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 funo %d segundos \n", hora_parada hora_inicio);
}

Na maioria dos sistemas, os clculos baseados em funes podem requerer quase o


dobro do tempo de processamento. Portanto, quando usar funes dentro dos
programas, necessrio considerar os benefcios que elas oferecem versus a sobrecarga
no desempenho que introduzem.

3.13 Declarando Variveis Globais


Alm das variveis locais, a Linguagem C permite que os programas usem variveis
globais, cujos nomes, valores e existncia so conhecidos em todo o programa. Em
outras palavras, todos os programas em Linguagem C podem usar variveis globais. O
programa a seguir ilustra o uso de trs variveis globais a, b e c:
#include <stdio.h>
int a = 1, b = 2, c = 3;

/* Variaveis globais */

void valores_globais(void)
{
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
valores_globais();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}

Quando este programa compilado e executado, as funes variaveis_globais e main


exibem os valores da varivel global. Observe que as variveis globais so declaradas fora de
todas as funes. Declarando variveis globais deste modo, todas as funes do programa
podem usar e alterar os valores da varivel global simplesmente referenciando o nome da
varivel global. Embora as variveis globais possam parecer convenientes, o uso incorreto
delas podem causar erros que so difceis de depurar.

3.14 Solucionando os Conflitos de Nomes de Variveis Locais


e Globais
Se um programa usa variveis globais, algumas vezes o nome de uma varivel global
o mesmo que aquele de uma varivel local que seu programa declara dentro de uma funo.
Por exemplo, o programa a seguir usa as variveis globais a, b e c. A funo conflito_a usa uma
varivel local chamada a e as variveis globais b e c:
#include <stdio.h>
int a=1, b=2, c=3;

/* Variveis globais */

void conflito_a(void)
{
int a=100;
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
conflito_a();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}

Quando nomes de variveis globais e locais estiverem em conflito, a Linguagem C usar


sempre a varivel local. Como voc pode ver, as alteraes que a funo conflito_a fez na
varivel a somente aparecem dentro da funo.

3.15 Chamada por Valor


Os programas passam informaes para funes usando parmetros. Quando um
parmetro passado a uma funo, a Linguagem C usa uma tcnica conhecida como chamada
por valor para fornecer funo uma cpia dos valores dos parmetros. Usando a chamada
por valor, quaisquer modificaes que a funo fizer nos parmetros existem apenas dentro da
prpria funo. Quando a funo termina, o valor das variveis que a funo chamadora
passou para a funo no modificada dentro da funo chamadora. Por exemplo, o
programa a seguir passa trs parmetros (as variveis a, b e c) para a funo exibe_e_altera. A
funo, por sua vez, exibir os valores, somar 100 aos valores e depois exibir o resultado.
Quando a funo terminar, o programa exibir os valores das variveis. Como a Linguagem C

usa chamada por valor, a funo no altera os valores das variveis dentro do chamador, como
mostrado a seguir:
#include <stdio.h>
void exibe_e_altera(int primeiro, int segundo, int terceiro)
{
printf("Valores originais da funo %d %d %d\n",
primeiro, segundo, terceiro);
primeiro += 100;
segundo += 100;
terceiro += 100;
printf("Valores finais da funo %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);
}

Como pode ser visto, as alteraes que a funo faz nas variveis somente so visveis
dentro da prpria funo. Quando a funo termina, as variveis dentro de main esto
inalteradas.

3.16 - Chamada por Referncia


Usando a chamada por valor, as funes no podem modificar o valor de uma varivel
passada para uma funo. No entanto, na maioria dos programas, as funes modificaro as
variveis de um modo ou de outro. Por exemplo, uma funo que l informaes de um
arquivo precisa colocar as informaes em uma matriz de string de caracteres. Da mesma
forma, uma funo tal como strupr precisa converter as letras em uma string de caractere para
maisculas. Quando as funes alteram o valor de um parmetro, os programas precisam
passar o parmetro para a funo usando chamada por referncia. A diferena entre chamada
por valor e chamada por referncia que, usando a chamada por valor, as funes recebem

uma cpia do valor de um parmetro. Por outro lado, com a chamada por referncia, as
funes recebem o endereo de memria da varivel. Portanto, as funes podem alterar o
valor armazenado na posio de memria especfica (em outras palavras, o valor da varivel);
alteraes essas que permanecem aps a funo terminar. Para usar a chamada por
referncia, seu programa precisar usar Ponteiros. O Mdulo sobre Ponteiros, mais adiante,
discute os Ponteiros em detalhes. No entanto, por ora, pense em um Ponteiro simplesmente
como um endereo de memria. Para atribuir o endereo de uma varivel a um ponteiro,
necessrio usar o operador de endereo "&". Para acessar posteriormente o valor na posio
de memria para o qual o Ponteiro aponta, use o operador de direo "*".

3.17 Obtendo um Endereo


Uma varivel essencialmente um nome atribudo a uma ou mais posies de memria.
Quando um programa roda, cada varivel reside em um seu prprio endereo de
memria. O programa localiza as variveis na memria usando o endereo de memria
da varivel. Para determinar o endereo de uma varivel, usa-se o operador de endereo
"&". Por exemplo, o programa a seguir usa o operador de endereo para exibir o
endereo (em hexadecimal) das variveis a., b e c:
#include <stdio.h>
void main(void)
{
int a=1, b=2, c=3;
printf("O endereo de a %x o valor de a %d\n", &a, a);
printf("O endereo de b %x o valor de b %d\n", &b, b);
printf("O endereo de c %x o valor de c %d\n", &c, c);
}

Para os programas passarem parmetros para funes cujos valores a funo


precisa alterar, os programas passaro as variveis por referncia (endereo de
memria), usando o operador de endereo, como mostrado a seguir:
alguma_funcao(&a, &b, &c);

3.18 Usando um Endereo de Memria


Quando se passa um endereo para uma funo, precisa-se informar ao compilador
que a funo estar usando um ponteiro (o endereo de memria) de uma varivel, e no o
valor de uma varivel. Para fazer isto, necessrio declarar uma varivel ponteiro. Declarar
uma varivel ponteiro muito similar declarao de uma varivel padro, em que se
especifica um tipo e o nome da varivel. A diferena, no entanto, que um asterisco (*)

precede os nomes das variveis ponteiro. As declaraes a seguir criam variveis ponteiro do
tipo int, float e char:
int *i_ponteiro;
float *f_ponteiro;
char *c_ponteiro

Aps declarar uma varivel ponteiro, precisa atribuir um endereo de memria


ela. Por exemplo, o comando a seguir, atribui o endereo da varivel inteira a varivel
ponteiro i_ponteiro:
i_ponteiro = &a;

Em seguida, para usar o valor apontado para a varivel ponteiro, os programas precisam
usar o operador de redireo da Linguagem C - o asterisco (*). Por exemplo, o
comando a seguir atribui o valor 5 varivel a (cujo endereo est contido na varivel
i_ponteiro):
i_ponteiro = 5;

De um modo similar, o comando a seguir atribui varivel b o valor ao qual a


varivel i_ponteiro aponta atualmente:
b = *i_ponteiro;

Quando quiser usar o valor apontado por uma varivel ponteiro, usa-se o operador de
redireo (*). Quando quiser atribuir o endereo de uma varivel uma varivel
ponteiro, usa-se o operador de endereo (&). O programa a seguir ilustra o uso de uma
varivel ponteiro. Ele atribui varivel ponteiro i_ponteiro o endereo da varivel O
programa ento usa a varivel ponteiro para alterar, exibir e atribuir o valor da varivel:
#include <stdio.h>
void main(void)
{
int a = 1, b = 2;
int *i_ponteiro;
i_ponteiro = &a;
*i_ponteiro = 5;
para 5 */

/* Atribui um endereo*/
/* Altera o valor apontado por i_ponteiro

printf("O valor apontado por i_ponteiro %d a variavel a


%d\n",*i_ponteiro, a);
/* Exibe o valor */
b = *i_ponteiro;

/* Atribui o valor */

printf("O valor de b %d\n", b);


printf("Valor de i_ponteiro %x\n", i_ponteiro);
}

3.19 Alterando o Valor de um Parmetro


Como foi visto anteriormente, para alterar o valor de um parmetro dentro de uma
funo, os programas precisam usar a chamada por referncia, passando o endereo da
varivel. Dentro da funo, precisa-se usar ponteiros. O programa a seguir usa ponteiros e
endereos (chamada por referncia) para exibir e, depois, alterar os parmetros que o
programa passa para a funo exibe_e_altera:
#include <stdio.h>
void exibe_e_altera(int *primeiro, int *segundo, int
*terceiro)
{
printf("Valores originais da funo %d %d %d\n",*primeiro,
*segundo, *terceiro);
*primeiro += 100;
*segundo += 100;
*terceiro += 100;
printf("Valores finais da funo %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);
}

3.20 Alterando Somente Parmetros Especficos

Como foi visto, as funes podem modificar o valor de um parmetro usando a


chamada por referncia. Por exemplo, o item anterior, apresentou a funo exibe_e_altera,
que usou chamada por referncia para alterar o valor de cada um de seus parmetros. No
entanto, em muitos casos, suas funes podem alterar o valor de um parmetro e ao mesmo
tempo deixar o valor de um segundo parmetro inalterado. Por exemplo, o programa a seguir
usa a funo muda_primeiro para atribuir ao parmetro primeiro o valor do parmetro
segundo:
#include <stdio.h>
void muda_primeiro(int *primeiro, int segundo)
{
*primeiro = segundo;
/* Atribui o valor de segundo a primeiro */
}
void main(void)
{
int a = 0, b = 5;
muda_primeiro(&a, b);
printf("Valor de a %d

valor de b %d\n", a, b);

Como pode ser visto, a funo muda_primeiro usa a chamada por referncia para
alterar o valor do parmetro primeiro, e chamada por valor para o parmetro segundo.
Quando os programas usam ambas as tcnicas, precisa ter-se em mente quando usar
ponteiros e quando referenciar diretamente a varivel. Como regra, os parmetros cujos
valores sero alterados iro requerer chamada por referncia. Para compreender melhor o
impacto da chamada por referncia versus chamada por valor, modifique a funo
muda_primeiro, como mostrado aqui:
void muda_primeiro(int *primeiro, int segundo)
{
*primeiro = segundo; /*Atribui o valor de segundo a primeiro*/
segundo = 100;
}

Quando este programa for compilado e executado, ver que o valor de primeiro foi
alterado, mas o valor de segundo no foi. Como o parmetro segundo foi passado usando
chamada por valor, a alterao do parmetro visvel fora da funo.

3.21 Funes Recursivas


Em C, as funes podem chamar a si prprias. Uma funo recursiva se um comando
no corpo da funo chama ela mesma. Algumas vezes chamada de definio circular, a
recursividade o processo de definio de algo em termos de si mesmo.
Exemplos de recursividade existem em grande nmero. Uma maneira de definir um
nmero inteiro sem sinal por meio de recursividade utilizando-se os dgitos 0, 1, 2, 3, 4, 5, 6,
7, 8, 9 mais ou menos outro nmero inteiro. Por exemplo, o nmero 15 o nmero 7 mais o
nmero 8; 21 9 mais 12 e 12 9 mais 3.
Para uma linguagem ser recursiva, uma funo deve estar apta a chamar a si prpria. O
exemplo clssico de recursividade mostrado na funo fatorial_recursivo(), que calcula o
fatorial de um nmero inteiro. O fatorial de um nmero N o produto de todos os nmeros
inteiros entre 1 e N. Por exemplo, o fatorial de 3 1 x 2 x 3, ou 6. Tanto a funo
fatorial_recursivo( ) como sua equivalente interativa so mostradas aqui:
#include <stdlib.h>
#include <stdio.h>
unsigned long int fatorial_recursivo (int n){
unsigned long int resposta;
if ((n == 1) || (n == 0))return(1);
resposta = n * fatorial_recursivo(n 1);
return(resposta);
void main()
{
unsigned long f;
int n;
printf(Digite um nmero: );
scanf(%d,&n);
f = fatorial_recursivo(n);

printf(O fatorial de %d %ld\n, n, f);


}
#include <stdlib.h>
#include <stdio.h>
unsigned long int fatorial (int n){
unsigned long int t, resposta;
resposta = 1;
for (t = 1; t < n; t++) resposta = resposta * t;
return(resposta);
void main()
{
unsigned long f;
int n;
printf(Digite um nmero: );
scanf(%d,&n);
f = fatorial(n);
printf(O fatorial de %d %ld\n, n, f);
}

Quando uma funo chama a si prpria, as novas variveis locais e os argumentos so


alocados na pilha, e o cdigo da funo executado com esses novos valores a partir do incio.
Uma chamada recursiva no faz uma nova cpia da funo. Somente os argumentos e as
variveis so novos. Quando cada chamada recursiva retorna, as antigas variveis locais e os
parmetros so removidos da pilha e a execuo recomea no ponto de chamada da funo
dentro da funo.
Tendo em vista que o local para os argumentos de funes e para as variveis locais
a pilha e que a cada nova chamada criado uma cpia destas variveis na pilha, possvel
ocorrer overflow da pilha (stack overflow) e o programa terminar com um erro.

3.22 Sntese do Mdulo

apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
3.1 Funes: dada uma explicao detalhada sobre as caractersticas gerais de
funes na Linguagem C.
3.2 Variveis dentro das Funes: foi visto que possvel e muito valioso o uso
de variveis dentro das funes. Foi mostrado que as variveis declaradas dentro de uma
funo, so vlidas apenas para aquela funo.
3.3 Main como uma Funo: foi visto que quando um programa criado, usa-se
o nome da funo main para determinar o primeiro comando que o programa executar. A
funo main a principal funo em um programa.
3.4 Introduo aos Parmetros: foi visto que um parmetro uma valor
passado a uma funo. Com eles a funo se torna mais til ao programa e facilita vria
operaes.
3.5 Parmetros Mltiplos: foi mostrado que em geral, pode-se passar um
nmero irrestrito de parmetros para uma funo. Quando a funo usa mais de um
parmetro, precisa especificar o tipo e o nome de cada parmetro e separar os parmetros por
vrgulas.
3.6 Retornando um Valor de uma Funo: foi visto que funes usam o
comando return para retornar o resultado do clculo ao chamador. O tipo de valor que a
funo retorna (int, float, char, etc.) determina o tipo da funo. Os valores que so passados
para uma funo precisam corresponder aos tipos de parmetros contidos dentro da
declarao dessa funo.
3.7 Comando Return: foi visto que quando a Linguagem C encontra um
comando return em uma funo, ela finaliza imediatamente a execuo da funo e retorna o
valor especificado para o chamador. O programa no executa quaisquer outros comandos
dentro da funo aps o comando return. Em vez disso, ele continua a execuo da funo
chamadora.
3.8 Prottipos de Funo: foi explicado que o prottipo de uma funo
especifica os tipos de parmetro e de retorno da funo.
3.9 Biblioteca de Execuo: foi explicado que a maioria dos compiladores
fornece centenas de funes de biblioteca de execuo com propsito que vo de abertura e
trabalho com arquivos para acessar informaes do disco ou de diretrio para determinar o
tamanho de uma string de caracteres, poupando horas de trabalho de programao.
3.10 Funes que no Retornam Int: foi visto que quando uma determinada
funo no retorna um valor do tipo int (em vez disso ela pode retornar float, double, char,
etc.) precisa-se informar ao compilador o tipo de retorno da funo.

3.11 Variveis Locais: foi explicado que variveis so locais, quando seus nomes
e valores somente tm significado dentro da funo que contm a declarao da varivel.
3.12 Sobrecarga da Funo: foi visto que a quantidade de tempo que o
computador requer para colocar e retirar informaes da pilha de sobrecarga da funo. Este
tempo tem um papel fundamental no desempenho dos programas em execuo.
3.13 Declarando Variveis Globais: foi visto que variveis globais so aquelas
cujos nomes, valores e existncia so conhecidos em todo o seu programa. Foi visto tambm
como declar-las.
3.14 Solucionando os Conflitos de Nomes de Variveis Locais e Globais: foi
visto que quando nomes de variveis globais e locais estiverem em conflito, a Linguagem C
usar sempre a varivel local.
3.15 Chamada por Valor: foi explicado que na chamada por valor, quaisquer
modificaes que a funo fizer nos parmetros existem apenas dentro da prpria funo.
Quando a funo termina, o valor das variveis que a funo chamadora passou para a funo
no modificada dentro da funo chamadora.
3.16 Chamada por Referncia: foi visto que quando as funes alteram o valor
de um parmetro, os programas precisam passar o parmetro para a funo usando chamada
por referncia.
3.17 Obtendo um Endereo: foi visto que para determinar o endereo de uma
varivel, usa-se o operador de endereo "&".
3.18 Usando um Endereo de Memria: foi visto que quando se passa um
endereo para uma funo, precisa-se informar ao compilador que a funo estar usando um
ponteiro (o endereo de memria) de uma varivel, e no o valor de uma varivel. Para fazer
isto, necessrio declarar uma varivel ponteiro.
3.19 Alterando o Valor de um Parmetro: foi mostrado um programa que usa
ponteiros e endereos (chamada por referncia) para exibir e, depois, alterar os parmetros
que o programa passa para uma funo.
3.20 Alterando Somente Parmetros Especficos: foi mostrado como fazer para
que as funes alterem o valor de um parmetro e ao mesmo tempo deixe o valor de um
segundo parmetro inalterado.
3.21 Funes Recursivas: foi explicado que uma funo recursiva se um
comando no corpo da funo chama ela mesma. Alm disso, foi dada uma viso geral sobre
funes recursivas.

Matrizes
Objetivos
Neste artigo estudaremos os conceitos relacionados as matrizes unidimensionais
(vetores) e multidimensionais.

Pr-requisitos
Para um melhor aprendizado necessrio que o leitor tenha acompanhado o artigo
anterior, pois os artigos obedecem a uma seqncia.

Nota: Este artigo faz parte do curso de Linguagem C Bsico.

Definio de Matrizes em Linguagem C


As matrizes em geral so caracterizadas por se tratarem de uma nica varivel de um
determinado tamanho que guarda varias informaes do mesmo tipo. Essas informaes
so gravadas na memria seqencialmente e so referenciadas atravs de ndices. As
matrizes podem ser tanto unidimensionais (vetores) como multidimensionais.

Matrizes unidimensionais
So matrizes de uma nica dimenso. Essas matrizes tambm so chamadas de vetores.
A declarao de vetores em C deve obedecer a seguinte sintaxe:

Tipo nome_vetor[tamanho];

O tipo deve ser especificado conforme a tabela 2 do primeiro artigo. E o tamanho


representa a quantidade de elementos que esta matriz ir conter. importante dizer que
na linguagem c as matrizes comeam pelo ndice 0 que guarda o primeiro elemento da
matriz. Para entender melhor, considere que seja necessrio declarar um vetor do tipo
inteiro que contenha 10 elementos. Isto feito da seguinte forma:

int vetor_exemplo[9];

Isso por que a matriz vetor_exemplo vai de 0 a 9, ou seja, contm 10 elementos.


Tambm possvel inicializar o vetor no momento de sua declarao. Para isso veja a
sintaxe abaixo:

Tipo nome_vetor[tamanho]={lista_de_valores};

Sendo que todos os elementos da lista de valores devem ser separados por virgula e
serem todas do mesmo tipo de dados especificado. A seguir temos a declarao do
vetor_exemplo com os valores atribudos.

int vetor_exemplo[9]={0,1,2,3,4,5,6,7,8,9};
Exemplo de um programa completo utilizando vetores e outros conceitos estudados at
o momento.

#include<stdio.h>

void main()
{
int vet1[5]={1,2,3,4,5}; /*declarao e inicializao do vetor vet1*/
int vet2[5]={6,1,2,2,5}; /*declarao e inicializao do vetor vet2*/
int vetSoma[5]; /*declarao do vetor vetSoma que vai guardar o resutado da soma dos
dois vetores(vet1 e vet2).*/

int x;

printf("Este programa soma os dois vetores abaixo:\n");


printf("vet1={1,2,3,4,5}\n");
printf("vet2={6,1,2,2,5}\n");
printf("\n");
printf("vetor resultante da soma:\n");

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


{
vetSoma[x]=vet1[x]+vet2[x]; /*soma os valores*/
printf("vetSoma[%d]:%d\n",x,vetSoma[x]); /*exibe na tela*/
} /*fim do for*/

} /*fim do programa*/

O programa acima soma dois vetores (vet1 e vet2) e exibe sua resposta na tela. O
objetivo deste exemplo mostrar como declarar e inicializar um vetor. Veja a seguir a
sada do programa:

Este programa soma os dois vetores abaixo:


vet1={1,2,3,4,5}
vet2={6,1,2,2,5}

vetor resultante da soma:


vetSoma[0]:7

vetSoma[1]:3
vetSoma[2]:5
vetSoma[3]:6
vetSoma[4]:10

Os vetores so muito usados para criar uma string de caracteres, pois em C no existe
nenhum tipo de dados para definir uma string.A declarao de um vetor contendo uma
string sempre deve ser maior que o nmero de caracteres, pois o compilador acrescenta
automaticamente no final da string um espao nulo que indica o seu trmino. Este
segundo exemplo muito simples, mostra apenas como podem ser feitas a declarao e
inicializao de um vetor de string.

#include<stdio.h>

void main()
{
char c1 = 'a';
char vet1[30]="Aprendendo a mexer com string\n";

/*Imprimindo os dados na tela*/


printf("O tipo de dado char guarda apenas um caractere\n");
printf("A variavel c1 do tipo char contem o caractere: %c\n",c1);
printf("\n");
printf("Para trabalhar com uma string deve ser declarado um vetor do tipo char");
printf("\nO vetor do tipo char contem a string: %s",vet1);

} /*fim do programa*/

Sada do programa:

O tipo de dado char guarda apenas um caractere


A variavel c1 do tipo char contem o caractere: a

Para trabalhar com uma string deve ser declarado um vetor do tipo char
O vetor do tipo char contem a string: Aprendendo a mexer com string

Matrizes Bidimensionais
So matrizes linha-coluna, onde o primeiro ndice indica a linha e o segundo a coluna.
Esse tipo de matriz considerado o caso mais simples de matrizes multidimensionais.
Veja o programa abaixo:

#include<stdio.h>

void main()
{
int mat[2][2];
float det;
int x,y;

printf("Este programa calcula a determinante de uma matriz quadrada de ordem 2");


printf("\n\nEntre com os valores a da matriz:\n");
for(x=0;x<2;x++)
{

for(y=0;y<2;y++)
{
printf("mat[%d][%d]=",x+1,y+1);
scanf("%d",&mat[x][y]);
} /*fim do for*/
} /*fim do for*/

det=mat[0][0]*mat[1][1]-mat[1][0]*mat[0][1]; /*formula para calcular a determinante


*/
printf("Determinante da matriz = %f\n",det);

} /*fim do programa*/

Esse exemplo calcula a determinante de uma matriz de ordem 2 e atravs dele podemos
ver como deve ser feita a declarao de uma matriz bidimensional.

int mat[2][2];

Que a forma geral :

tipo nome_matriz[numero_linhas][numero_colunas];

Observe na formula que calcula a determinante que os valores so acessados atravs de


seus ndices (linhas e colunas). A seguir so apresentadas as sadas do programa,
lembrando que os valores das matrizes so definidos pelo usurio atravs da funo
scanf que ser explicada mais adiante.

Este programa calcula a determinante de uma matriz quadrada de ordem 2

Entre com os valores a da matriz:


Mat[1][1]=4
Mat[1][2]=-3
Mat[2][1]=6
Mat[2][2]=-1
Determinante da matriz = 14.0000

Matrizes multidimensionais
A linguagem c permite tambm utilizar matriz de trs ou mais dimenses, porm no
freqentemente usada, pois requer uma quantidade grande de memria e os acessos aos
seus elementos so mais lentos. Por esses motivos este tipo de matrizes no sero
abordados com detalhes

Declarao de matrizes multidimensionais:

Tipo nome [tamanho1][tamanho2][tamanho3]....[tamanho n]

Matrizes no-dimensionadas
As matrizes no-dimensionais so aquelas cujo tamanho no especificado. Nesse caso
o compilador cria uma matriz grande para conter todos os seus elementos. As
declaraes de matrizes unidimensionais com essa caracterstica podem ser vista no
programa abaixo:

#include<stdio.h>

void main()
{
char vet1[37]="Estou aprendendo a programar em C!!!";
char vet2[]="Estou aprendendo a programar em C!!!"; /*vetor no-dimensionado*/

printf("O vetor abaixo foi declarado com o seu tamanho especificado\n");


printf("%s\n",vet1);
printf("\n");
printf("E este outro foi declarado com o seu tamanho nao especificado\n");
printf("%s\n",vet2);

Observe na sada abaixo que os vetores (vet1 e vet2) declarados de forma diferentes
obtiveram os mesmo efeitos. A diferena que no vetor vet2 no foi especificado a
quantidades de caracteres (vetor no-dimensionado).

O vetor abaixo foi declarado com o seu tamanho especificado


Estou aprendendo a programar em C!!!

E este outro foi declarado com o seu tamanho nao especificado


Estou aprendendo a programar em C!!!

As matrizes multidimensionais no-dimensionadas devem ter apenas seu primeiro


ndice no especificado, os outros devem ser indicados para que o compilador possa
indexar de forma correta as matrizes. Desta forma pode-se criar tabelas com diversos
tamanhos, sem a necessidade de mudar as dimenses da matriz.

#include<stdio.h>

void main()
{
int mat1[2][2]={4,5,-2,1};
int mat2[][2]={4,5,-2,1}; /*Matriz no-dimensionada*/
int x,y;

printf("Imprimindo a matriz mat1 cujo o tamanho foi especificado:\n");


for(x=0;x<2;x++)
{
for(y=0;y<2;y++)
{
printf("mat1[%d][%d]=%d",x,y,mat1[x][y]);
printf("\n");
} /*fim do for*/
} /*fim do for*/

printf("\n");
printf("Imprimindo a matriz mat2 cujo o tamanho nao foi especificado:\n");
for(x=0;x<2;x++)
{
for(y=0;y<2;y++)
{

printf("mat2[%d][%d]=%d",x,y,mat2[x][y]);
printf("\n");
} /*fim do for*/
} *fim do for*/ /

} /*fim do programa*/

Do mesmo modo verifica-se atravs da sada abaixo que tanto a matriz mat1 como a
matriz mat2, obtiveram os mesmos resultados embora tenham sido declaradas de
maneira diferente.

Imprimindo a matriz mat1 cujo o tamanho foi especificado:


mat1[0][0]=4
mat1[0][1]=5
mat1[1][0]=-2
mat1[1][1]=1

Imprimindo a matriz mat2 cujo o tamanho nao foi especificado:


mat2[0][0]=4
mat2[0][1]=5
mat2[1][0]=-2
mat2[1][1]=1

Concluso

Conclui-se que as matrizes podem ser desde unidimensionais at multidimensionais e


que seus tamanhos no necessitam serem obrigatoriamente especificados.

Mdulo 6 Matrizes na Linguagem C


6.1 Compreendendo as Matrizes
Muitas vezes em programas, necessrio que uma varivel contenha muitos
valores. Por exemplo, a varivel nota pode controlar as notas obtidas por 100 alunos em
um exame. Da mesma maneira, a varivel salrios poderia controlar os salrios de cada
funcionrio em uma companhia. Uma matriz uma estrutura de dados que pode
armazenar mltiplos 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 mdulo ser mostrado como criar e trabalhar com matrizes em
programas. Com o tempo, aps o uso de matrizes, ficar claro como simples o uso de
matrizes.

6.2 Declarando uma Matriz


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 nmero de valores que a matriz pode armazenar dentro de colchetes
aps o nome da matriz. Por exemplo, a declarao seguir cria uma matriz chamada
notas, que pode armazenar 100 notas de exame do tipo int:
int notas [100];

De forma similar, a seguinte declarao cria uma matriz do tipo float, que
contm 50 salrios:
float salarios [50];

Quando uma matriz declarada, a Linguagem C aloca memria suficiente para


conter todos os elementos. O primeiro item est na posio 0. Por exemplo, nas matrizes
notas e salarios, 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 posio 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;

6.3 Compreendendo os Requisitos de Armazenamento de


uma Matriz
Ao declarar uma matriz, o compilador aloca memria suficiente para conter o
nmero de valores especificado. A quantidade real de memria 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 memria. 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 memria 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 string[100] %d bytes\n",
sizeof(string));
}

6.4 - Inicializando uma Matriz


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
tambm inicializar as posies 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 notas 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, necessrio delimitar os valores


por abre e fecha chaves ( {} ). No caso anterior, o tamanho da matriz igual ao nmero
de valores atribudos. 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 no atribui valores explcitos. No entanto, como regra, no se deve assumir
que o compilador inicializar os outros elementos. Alm disso, se no for especificado
um tamanho de matriz, o compilador alocar memria suficiente para conter somente os
valores que voc especificar. Por exemplo, a seguinte declarao de matriz cria uma
matriz grande o suficiente para conter trs valores do tipo long:
long planetas[] = {1234567L, 654321L, 1221311L};

6.5 Acessando Elementos da Matriz


Os valores armazenados em uma matriz so 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 notas 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]);
}

6.6 Percorrendo em um Lao Elementos da Matriz


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

matriz[i] = 80;

O cdigo a seguir usa a varivel i e um lao for para exibir os elementos da


matriz notas:
#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]);
}

6.7 Usando Constantes Para Definir as Matrizes


Como visto, quando os programas trabalham com matrizes, necessrio
especificar o tamanho da matriz. Por exemplo, o programa a seguir declara uma matriz
de cinco valores e depois usa um lao 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 necessrio alterar o cdigo anterior de tal forma
que ele suporte 10 valores. Precisar alterar no somente a declarao da matriz, mas
tambm o lao for. Quanto mais alteraes 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 no somente usa a constante para declarar a
matriz, mas tambm usa a constante como a condio final para o lao 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 necessrio alterar o tamanho da matriz, poder alterar o valor
atribudo constante TAM_MATRIZ para que o programa automaticamente atualize os
laos que controlam a matriz como o tamanho da matriz.

6.8 Passando uma Matriz a uma Funo


Quando declara-se uma funo que trabalha com um parmetro matriz, precisa
informar o compilador. Por exemplo, o seguinte programa usa a funo exibe_matriz
para exibir os valores em uma matriz. Como pode-se ver, o programa passa para a
funo tanto a matriz como o nmero de elementos que a matriz contm, 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 funo recebe uma matriz como parmetro, o programa no precisa
especificar o tamanho da matriz na declarao do parmetro. No caso da funo
exibe_valores, os colchetes aps o nome da varivel valor informam o compilador de
que o parmetro uma matriz. Sabendo que o parmetro uma matriz, o compilador
no se preocupa com o tamanho da matriz que o programa passa para a funo.

6.9 Revisitando as Matrizes Como Funes


No item anterior, foi visto que ao declarar o parmetro formal para uma matriz,
no necessrio declarar o tamanho da matriz. Em vez disso, pode-se especificar
somente o abre e fecha colchetes. O programa a seguir passa trs matrizes diferentes (de
diferentes tamanhos) para a funo exibe_valores:
#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};
int pequeno[2] = {-33, -44};

exibe_matriz(notas, 5);
exibe_matriz(conta, 10);
exibe_matriz(pequeno, 2);
}

6.10 Compreendendo Como as Matrizes de String Diferem


Muitos programas passam string para funes. Em muitos casos, as funes no
especificaram o tamanho da string. Por exemplo, o comando a seguir usa a funo
strupr para converter uma string para maisculas:
char titulo[64] = "Unesp Ilha Solteira";
strupr(titulo);

Como foi visto, na Linguagem C o caracter NULL representa o final de uma


string de caracteres. Portanto, as funes podem procurar o caracter NULL nos
elementos da matriz para determinar onde a matriz termina. No entanto, as matrizes de

outros tipos, tais como int, float ou long, no tem um caracter finalizador equivalente.
Portanto, voc normalmente precisa passar para as funes que trabalham com matrizes
o nmero de elementos que a matriz contm.

6.11 Determinando Quantos Elementos Uma Matriz Pode


Armazenar
J foi visto anteriormente que, dependendo do tipo de uma matriz, a quantidade
real de memria que uma matriz pode consumir diferir. Se o ambiente de trabalho for o
DOS, a quantidade de memria que as matrizes podem consumir depender do modelo
de memria atual. Em geral, uma matriz no pode consumir mais do que 64Kb de
espao. O programa a seguir pode no passar na compilao porque as matrizes
consomem muita memria:
void main(void)
{
char string[66000L];

/* 66,000 bytes */

int values[33000L];

/* 33,000 * 2 = 66,000 bytes */

float numbers[17000];

/* 17,000 * 4 = 68,000 bytes */

6.12 Compreendendo as Matrizes Multidimensionais


Como foi visto, uma matriz uma varivel que pode armazenar mltiplos
valores do mesmo tipo. Em todos os exemplos apresentados at o momento, as matrizes
consistiram de uma fileira de dados. No entanto, a Linguagem C permite matrizes bi, tri
e multidimensionais. O melhor modo de visualizar uma matriz bidimensional com
uma tabela com linhas e colunas. Se uma matriz contm trs dimenses, visualize-a
como vrias pginas, cada uma das quais contendo uma tabela bidimensional.
Por exemplo, ao declarar-se uma matriz bidimensional, o primeiro valor que for
especificado informar o nmero de linhas, e o segundo valor, o nmero de colunas:
int tabela [2] [3];

6.13 - Inicializando Elementos em Uma Matriz Bidimensional


No item 5.4 foi visto que, para inicializar elementos de matriz, voc pode
colocar os valores do elemento dentro de abre e fecha colchetes aps a declarao da
matriz. O comando a seguir usa a mesma tcnica para inicializar uma matriz
bidimensional. No entanto, neste caso, o comando especifica os valores para cada linha
da matriz dentro de chaves:
int tabela [2] [3] = {{1,2,3}, {4,5,6}};

O compilador inicializar os elementos da matriz como mostrado a seguir:


1

6.14 Percorrendo em Um Lao Uma Matriz Bidimensional


Quando os programas trabalham com matrizes bidimensionais, normalmente
usa-se duas variveis para acessar elementos da matriz. O programa a seguir usa as
variveis linha e coluna para exibir os valores contidos dentro da matriz tabela:
#include <stdio.h>
void main(void)
{
int linha, coluna;
float tabela[3][5] = {{1.0, 2.0, 3.0, 4.0, 5.0},
{6.0, 7.0, 8.0, 9.0, 10.0},
{11.0, 12.0, 13.0, 14.0, 15.0}};
for (linha = 0; linha < 3; linha++)
for (coluna = 0; coluna < 5; coluna++)
printf("tabela[%d][%d] = %f\n", linha, coluna,
tabela[linha][coluna]);
}

Colocando laos for um dentro do outro, como mostrado, o programa exibir os


elementos contidos na primeira linha da matriz (1.0 at 5.0). Em seguida, o programa ir
se mover para a prxima linha, e, depois, para a terceira linha, exibindo os elementos
dentro de cada linha.

6.15 Percorrendo Uma Matriz Tridimensional


No item anterior foi visto como percorrer uma matriz bidimensional usando duas
variveis chamadas linha e coluna. O programa a seguir usa as variveis linha, coluna e
tabela para percorrer uma matriz tridimensional:
#include <stdio.h>
void main(void)
{
int linha, coluna, tabela;
float valores[2][3][5] = {
{{1.0, 2.0, 3.0, 4.0, 5.0},

{6.0, 7.0, 8.0, 9.0, 10.0},


{11.0, 12.0, 13.0, 14.0, 15.0}},
{{16.0, 17.0, 18.0, 19.0, 20.0},
{21.0, 22.0, 23.0, 24.0, 25.0},
{26.0, 27.0, 28.0, 29.0, 30.0}}
};
for (linha = 0; linha < 2; linha++)
for (coluna = 0; coluna < 3; coluna++)
for (tabela = 0; tabela < 5; tabela++)
printf("valores[%d][%d][%d] = %f\n", linha,
coluna, tabela,
valores[linha][coluna][tabela]);
}

6.16 Passando uma Matriz Bidimensional Para uma Funo


No item 5.8, foi visto que, ao passar matrizes para uma funo, no ser
necessrio especificar o nmero de elementos na matriz. Em matrizes bidimensionais,
no ser necessrio especificar o nmero de linha na matriz, mas, sim, especificar o
nmero de colunas. O programa a seguir usa a funo exibe_2d_matriz para exibir o
contedo de variveis matrizes bidimensionais:
#include <stdio.h>
void exibe_2d_matriz(int matriz[][10], int linhas)
{
int i, j;
for (i = 0; i < linhas; i++)
for (j = 0; j < 10; j++)
printf("matriz[%d][%d] = %d\n", i, j, matriz[i][j]);
}
void main(void)
{

int a[1][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}};


int b[2][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18, 19,20}};
int c[3][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}};
exibe_2d_matriz(a, 1);
exibe_2d_matriz(b, 2);
exibe_2d_matriz(c, 3);
}

6.17 Tratando as Matrizes Multidimensionais Como Uma


Dimenso
Quando for necessrio trabalhar com os elementos de uma matriz
multidimensional, mas sem precisar acessar os elementos em suas posies de linha ou
coluna, as funes podero tratar a matriz multidimensional como se ela tivesse uma
dimenso. O programa a seguir retorna a soma dos valores em uma matriz
bidimensional:
#include <stdio.h>
long soma_matriz(int matriz[], int elementos)
{
long soma = 0;
int i;
for (i = 0; i < elementos; i++)
soma += matriz[i];
return(soma);
}
void main(void)
{
int a[10] =

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int b[2][10]={{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},

{11, 12, 13, 14, 15, 16, 17, 18, 19,20}};


int c[3][10]={{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27, 28, 29,30}};
printf("Soma dos elementos da primeira matriz %d\n",
soma_matriz(a, 10));
printf("Soma dos elementos da segunda matriz %d\n",
soma_matriz(b, 20));
printf("Soma dos elementos da terceira matriz %d\n",
soma_matriz(c, 30));
}

6.18 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste
mdulo. Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo
ou mesmo direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
6.1 Compreendendo as Matrizes: dada uma explicao que uma
matriz uma estrutura de dados que pode armazenar mltiplos valores do mesmo tipo.
6.2 Declarando uma Matriz: neste item visto como declarar uma
matriz, precisando-se especificar o tipo desejado (tal como int, float ou double), bem
como o tamanho da matriz.
6.3 Compreendendo os Requisitos de Armazenamento de uma
Matriz: foi visto que ao declarar uma matriz, o compilador aloca memria suficiente
para conter o nmero de valores especificado. A quantidade real de memria que o
compilador aloca depende do tipo da matriz.
6.4 Inicializando uma Matriz: neste item explicada de maneira clara
como inicializar diferentes tipos de matrizes.
6.5 Acessando Elementos da Matriz: foi visto que para acessar um
elemento da matriz, voc especifica o nome da matriz e o elemento que deseja.
6.6 Percorrendo em um Lao Elementos da Matriz: foi mostrado que
quando se referencia muitos elementos de uma matriz, especificar nmeros para cada
elemento da matriz individualmente pode ser demorado e tedioso. Como uma
alternativa, os programas podem usar uma varivel para referenciar os elementos da
matriz.
6.7 Usando Constantes Para Definir as Matrizes: mostra como os
programas usam constantes para definir matrizes.
6.8 Passando uma Matriz a uma Funo: visto que programas
passam para a funo tanto a matriz como o nmero de elementos que a matriz contm.

6.9 Revisitando as Matrizes Como Funes: . foi visto um programa


que passa trs matrizes diferentes (de diferentes tamanhos) para a funo exibe_valores.
6.10 Compreendendo Como as Matrizes de String Diferem: explica
as principais diferenas das matrizes de string.
6.11 Determinando Quantos Elementos Uma Matriz Pode
Armazenar: foi visto que se o ambiente de trabalho for o DOS, a quantidade de
memria que as matrizes podem consumir depender do modelo de memria atual. Em
geral, uma matriz no pode consumir mais do que 64Kb de espao.
6.12 Compreendendo as Matrizes Multidimensionais: foi visto que a
Linguagem C permite matrizes bi, tri e multidimensionais.
6.13 Inicializando Elementos em Uma Matriz Bidimensional: foi
mostrado como inicializar uma matriz bidimensional.
6.14 Percorrendo em Um Lao Uma Matriz Bidimensional: foi
mostrado um programa que usa as variveis linha e coluna para exibir os valores
contidos dentro da matriz tabela.
6.15 Percorrendo Uma Matriz Tridimensional: foi mostrado um
programa que usa as variveis linha, coluna e tabela para percorrer uma matriz
tridimensional.
6.16 Passando uma Matriz Bidimensional Para uma Funo: foi
visto que para passar matrizes bidimensionais para uma funo, no ser necessrio
especificar o nmero de linha na matriz, mas, sim, especificar o nmero de colunas.
6.17 Tratando as Matrizes Multidimensionais Como Uma
Dimenso: foi visto que quando for necessrio trabalhar com os elementos de uma
matriz multidimensional, mas sem precisar acessar os elementos em suas posies de
linha ou coluna, as funes podero tratar a matriz multidimensional como se ela tivesse
uma dimenso.

Ponteiros
Objetivos

Neste artigo estudaremos o que so ponteiros, qual a sua importncia e como utiliza-los.

Pr-requisitos

necessrio que o leitor tenha acompanhado o artigo anterior, pois os artigos obedecem
a uma seqncia.

Nota: Este artigo faz parte do curso de Linguagem C Bsico.

Ponteiros
O ponteiro nada mais do que uma varivel que guarda o endereo de uma outra
varivel. A declarao de ponteiros feita da seguinte forma:

A instruo acima indica que pa um ponteiro do tipo int. Agora veremos como atribuir
valor ao ponteiro declarado. Para isto necessrio saber que existem dois operadores
unitrios que so utilizados com os ponteiros. O primeiro o operador (*) atravs dele
possvel retornar o valor da varivel que est localizada no ponteiro. E o segundo o
operador (&) que retorna o endereo de memria que est localizado o valor da variavel
contida no ponteiro. Portanto para atribuirmos um valor para o ponteiro necessrio
referencia o valor da varivel que se encontra no ponteiro utilizando o operador (*),
como ser demonstrado a seguir.

Desta forma estamos atribuindo o valor 24 para a varivel que est contida no ponteiro.
Para entender melhor quando e como utilizar os operadores (*) e (&), veja o programa
mostrado abaixo.

Sada do programa:

Quando os ponteiros so declarados, eles so inicializados com um endereo no valido,


portanto antes de usa-los necessrio atribuir um endereo e isso feito atravs do
operador (&) como demonstra a instruo pa=&a e pb=&b que atribui aos ponteiros pa
e pb o endereo das varieis a e b.

Uma outra novidade do programa anterior quando queremos imprimir o


endereo do prprio ponteiro isto feito referenciando pa normalmente. Porm para
imprimir o endereo contido no ponteiro usado &pa e por ultimo para imprimir o
valor do endereo contido no ponteiro usamos *pa.

Atravs do programa abaixo possvel verificar que se pode fazer comparaes entre
ponteiros.

Sada do programa:

A comparao entre ponteiros em uma expresso relacional (>=,<=,> e <) possvel


quando os dois ponteiros so do mesmo tipo. Isso feito no programa mostrado atravs
da linha if (px1>px2), Caso a instruo seja verdadeira ser feita a diferena entre os
dois ponteiros px1-px2. E caso seja falso ser feito ao contrario px2-px1.
importante dizer que os dados de sada deste programa no so iguais em todos os
computadores, depende muito da memria disponvel. Mas como pode-se observar em
nosso exemplo, se px1=1245064 e px2=1245060 ento px1-px2 ser igual a um. Isso
ocorre, pois a diferena depende da unidade tipo apontado. Para entender melhor, veja
alguns casos de operaes com ponteiros. Se um ponteiro do tipo inteiro px1 fosse igual
a 150 e que os inteiros possuem dois bytes. As operaes que se podem fazer so as
seguintes: Incrementar o ponteiro atravs da expresso:

Isso far com que o ponteiro aponte para a posio do prximo elemento. Como
estamos a considerar que o tipo inteiro do tamanho de 2 bytes, o ponteiro est sendo
incrementado de 2, ou seja, o nmero de incrementos depende do tamanho do tipo de
dados. O mesmo acontece com o decremento, porm aponta para a posio anterior.
Isso feito pela instruo:

Isso far com que o ponteiro aponte para a posio do prximo elemento. Como
estamos a considerar que o tipo inteiro do tamanho de 2 bytes, o ponteiro est sendo
incrementado de 2, ou seja, o nmero de incrementos depende do tamanho do tipo de
dados. O mesmo acontece com o decremento, porm aponta para a posio anterior.
Isso feito pela instruo:

Uma outra opo somar ou diminuir inteiros ao ponteiro:

Dessa forma o ponteiro ir apontar para o quinto elemento do tipo px1 adiante do
elemento que o ponteiro estava a apontar. importante saber que no se pode nem
multiplicar e nem dividir ponteiros.

Do mesmo modo que se tem um ponteiro (que o endereo de uma varivel) pode-se
ter ponteiro para ponteiro, ou seja, um ponteiro aponta para um outro ponteiro que
finalmente aponta para a varivel com o valor a ser utilizado. O que chamamos de
indireo mltipla e pode ser vista no prximo programa.

Dados de sada:

Como visto no cdigo fonte anterior, uma varivel que ponteiro para ponteiro deve ser
declarada da seguinte forma:

Da mesma forma para acessar o valor final utilizado o operador * duas vezes,
conforme visto no neste exemplo.

Concluso
Neste artigo vimos que um ponteiro uma varivel que guarda um endereo de uma
outra varivel. Estudamos como declara-las e que antes de utiliza-las necessrio
atribuir um endereo vlido. Foi visto tambm que podemos utilizar ponteiros para
ponteiros. Tudo isto foi mostrado com exemplos simples e didticos. Conclui-se, no
entanto que o uso de ponteiro importante em muitos casos e que se deve tomar muito
cuidado ao usa-los. Nos prximos artigos sero estudadas algumas situaes em que
ponteiros so muito teis. Como por exemplo: o uso de ponteiros para mudar os
argumentos das funes e as alocaes dinmicas.

Mdulo 7 Ponteiros
7.1 Ponteiros como Endereos
Como j foi visto, uma varivel o nome de uma posio na memria que pode
armazenar um valor de um determinado tipo. Os programas referenciam cada posio
na memria usando um endereo exclusivo. Um ponteiro uma varivel ou um valor
que contem um endereo. A Linguagem C utiliza muito os ponteiros. Quando se passa
matrizes ou string para as funes, o compilador C passa um ponteiro. Da mesma
forma, quando uma funo precisa alterar o valor de um parmetro, o programa deve
passar para a funo um ponteiro para o endereo de memria da varivel.

7.2 Determinando o Endereo de uma Varivel


Um ponteiro um endereo de uma posio na memria. 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

endereo de uma varivel, devero usar o operador de endereo da Linguagem C


&.
Por exemplo, o programa a seguir usa o operador de endereo para exibir o endereo de
vrias variveis diferentes:
#include <stdio.h>
void main(void)
{
int conta = 1;
float salario = 40000.0;
long distancia = 1234567L;
printf("O endereo de conta %x\n", &conta);
printf("O endereo de salario %x\n", &salario);
printf("O endereo de distancia %x\n", &distancia);
}

7.3 Como a Linguagem C trata Matrizes como Ponteiros


J foi visto anteriormente que um compilador C trata as matrizes como
ponteiros. Por exemplo, quando um programa passa uma matriz para uma funo, o
compilador passa o endereo inicial da matriz.
O programa a seguir exibe o endereo inicial de vrias matrizes diferentes:
#include <stdio.h>
void main(void)
{
int conta[10];
float salarios[5];
long distancia[10];
printf("O endereo da matriz conta %x\n", conta);
printf("O endereo da matriz salarios %x\n", salarios);
printf("O endereo da matriz distancia %x\n", distancia);
}

7.4 Aplicando o Operador de Endereo (&) a uma Matriz


Se o operador de endereo for aplicado a uma matriz, a Linguagem C retornar
o endereo inicial da matriz. Portanto, aplicar o operador de endereo a uma matriz
redundante. O programa a seguir exibe o endereo inicial de uma matriz, seguido pelo
ponteiro que o operador de endereo retorna:
#include <stdio.h>
void main(void)
{
int conta[10];
float salarios[5];
long distancias[10];
printf("O endereo da matriz conta %x &conta %x\n",
conta, &conta);
printf("O endereo da matriz salarios %x &conta %x\n",
salarios, &salarios);
printf("O endereo da matriz distancias %x &distancias
%x\n", distancias, &distancias);
}

7.5 Declarando Variveis Ponteiros


medida que os programas tornarem-se mais complexos, ponteiros so usados
com muita freqncia. Para armazenar ponteiros, os programas precisam declarar
variveis ponteiros. 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 varivel. Por exemplo, o comando a seguir declara um ponteiro para um valor do tipo
int:
int *iptr;

Como qualquer varivel, precisa-se atribuir um valor a uma varivel ponteiro


antes de poder usar o ponteiro dentro do programa. Quando atribui-se um valor a um
ponteiro, realmente atribui um endereo. Assumindo que anteriormente tenha-se
declarado int conta, o comando a seguir atribui o endereo da varivel conta ao ponteiro
iptr:
iptr = &conta;

/* Atribui o endereo de conta a iptr */

O programa a seguir declara a varivel ponteiro iptr e atribui ao ponteiro o


endereo da varivel conta. O programa ento exibe o valor da varivel ponteiro,
juntamente com o endereo de conta:

#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 Endereo de conta
%x\n", iptr, conta, &conta);
}

7.6 Desreferenciando um Ponteiro


Desreferenciar um ponteiro o processo de acessar o valor de uma posio de
memria especfica. Para desreferenciar o valor de um ponteiro, usa-se o operador
asterisco de indireo (*). Por exemplo, o comando printf a seguir exibe o valor
apontado pelo ponteiro inteiro iptr:
printf(O valor apontado po iptr %d\n, *iptr);

Da mesma forma, o comando a seguir atribui o valor apontado pela varivel iptr
para a varivel conta:
conta = *iptr;

Finalmente, o comando a seguir atribui o valor 7 posio de memria apontada


por iptr:
*iptr = 7;

7.7 Usando Valores de Ponteiro


O programa a seguir atribui ao ponteiro int iptr o endereo da varivel conta. O
programa depois exibe o valor do ponteiro e o valor armazenado na posio apontada
pelo ponteiro (o valor contador).
O programa ento 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 endereo */

printf("Endereo em iptr %x Valor em *iptr %d\n", iptr, *iptr);


*iptr = 25;

/* Altera o valor na memria */

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


}

7.8 Ponteiros com Parmetros de Funo


O Mdulo de Funes examina em detalhes o processo de passar parmetros
para as funes. Quando for necessrio alterar o valor de um parmetro, dever passar
para a funo um ponteiro para um parmetro. O programa a seguir usa os ponteiros
para dois parmetros do tipo int para permutar os valores das variveis, 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 contm %d dois contm %d\n", um, dois);
}

Como pode ser visto, dentro da funo, os comandos desreferenciam os


ponteiros usando o operador de indireo (*). O programa passa o endereo de cada
varivel para a funo usando o operador de endereo (&).

7.9 A Aritmtica de Ponteiros


Um ponteiro um endereo que aponta para um valor de um determinado tipo na
memria. Nos termos mais simples possveis, um ponteiro um valor que aponta para
uma posio de memria especfica. Se somar-se o valor 1 a um ponteiro, o ponteiro

apontar para a prxima posio de memria. Se somar-se 5 ao valor de um ponteiro, o


ponteiro apontar para a posio de memria de cinco posies adiante do endereo
atual. No entanto, a aritmtica de ponteiro no to simples quanto parece. Por
exemplo, assuma que um ponteiro contenha o endereo 1000. Se fosse somado 1 ao
ponteiro, poderia se esperar que o resultado fosse 1001. No entanto, o endereo
resultante depende do tipo de ponteiro. Por exemplo, se fosse somado 1 a um ponteiro
do tipo char (que contm 1000), o endereo resultante ser 1001. Se fosse somado 1 a
um ponteiro do tipo int (que requer dois bytes na memria), o endereo resultante ser
1002. Quando for efetuada a aritmtica de ponteiro necessrio ter em mente o tipo de
ponteiro. Alm de somar valores aos ponteiros, os programas podero subtrair valores
ou somar e subtrair dois ponteiros.

7.10 Incrementando e Decrementando um Ponteiro


Uma das operaes mais comuns com ponteiros o incremento e o decremento
do valor de um ponteiro para apontar para a prxima posio ou para a posio anterior
na memria. O programa a seguir atribui o endereo inicial de uma matriz de valores
inteiros ao ponteiro iptr. O programa depois incrementa o valor do ponteiro para exibir
os cinco elementos que a matriz contm:
#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++;
}
}

7.11 - Percorrendo uma String usando um Ponteiro


Uma string uma matriz de caracteres terminada p NULL. O programa a
seguir usa a funo exibe_string 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 funo exibe_string declara a varivel string como um
ponteiro. Usando o ponteiro, a funo simplesmente percorre os caracteres da string at
encontrar o caractere NULL. Para exibir o caractere, a funo exibe_string primeiro
desreferencia o endereo do ponteiro (obtendo o caractere). Em seguida, a funo
incrementa o ponteiro para apontar para o prximo caractere na string.

7.12 - Funes que retornam Ponteiros


O valor que uma funo retorna sempre do tipo declarado no prottipo ou
cabealho da funo. Alm de retornar esses tipos bsicos, as funes podem declarar
ponteiros para os valores. Por exemplo, a funo fopen, que a maioria das funes 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);

7.13 Criando uma Funo que retorna um Ponteiro


O programa a seguir cria uma funo chamada string_maiusc que converte
todos os caracteres de uma string para maisculas 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_maiusc(titulo);
printf("%s\n", string);
printf("%s\n", string_maiusc("Matrizes e Ponteiros"));
}

7.14 - Uma Matriz de Ponteiros


Assim como pode-se criar funes que retornam ponteiros, tambm pode-se
criar matrizes de ponteiros. Mais comumente sero usadas matrizes para conter strings
de caracteres.
Como exemplo, a declarao a seguir cria uma matriz chamada dias que contm
ponteiros para string de caracteres:
char *dias[7]= {Domingo,
Sexta, Sbado};

Segunda,

Tera,

Quarta,

Quinta,

Se for examinado o tipo da matriz da direita para a esquerda, ser visto que a
matriz contm sete elementos. O asterisco antes do nome da varivel especifica um
ponteiro. Se combinar o nome do tipo char que precede o nome da varivel, a
declarao se tornar uma matriz de ponteiros para strings de caractere.

7.15 - Percorrendo em um Lao uma Matriz de Strings de


Caracteres
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 lao a matriz dias, que contm ponteiros
para strings que contm os nomes dos dias da semana, como mostrado aqui:
#include <stdio.h>
void main(void)
{
char *dias[7] = {"Domingo", "Segunda", "Tera",
"Quarta", "Quinta", "Sexta", "S bado"};

int i;
for (i = 0; i < 7; i++)
printf("dias[%d] contm %s\n", i, dias[i]);
}

7.16 Usando um Ponteiro para um Ponteiro para String de


Caracteres
A declarao 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 contedo da matriz diasuteis:
#include <stdio.h>
void main(void)
{
char *diasuteis[] = {"Segunda", "Tera", "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 dia_til o endereo inicial da


matriz diasuteis (o endereo da string Segunda). O programa repete ento um lao at
encontrar o ponteiro para a string NULL (a condio final).

7.17 Declarando uma Constante String usando um Ponteiro


Muitas vezes strings de caracteres so inicializadas como segue:
char titulo[] = Unesp Ilha Solteira;

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


memria suficiente para armazenar os caracteres especificados (e o terminador NULL),
atribuindo varivel titulo um ponteiro para o primeiro caractere. Como o compilador C
automaticamente aloca a memria necessria e depois trabalha com um ponteiro para a
memria, os programas podem usar um ponteiro de string de caracteres, em vez de uma
matriz, como mostrado a seguir:
char *titulo = Unesp Ilha Solteira;

7.18 O Ponteiro do tipo Void


Ao declarar uma varivel ponteiro, preciso especificar o tipo do valor para o
qual o ponteiro aponta. Quanto se faz isso, o compilador pode, mais tarde, efetuar
aritmtica de ponteiros corretamente e adicionar os valores de deslocamentos corretos
quando incrementar ou decrementar o ponteiro. Em alguns casos, no entanto, os
programas no manipularo o valor de um ponteiro de qualquer maneira. Em vez disso,
os programas somente iro obter um ponteiro para uma posio de memria com a qual
o programa determinar o uso do ponteiro.
Nesses casos, os programas podero criar um ponteiro para o tipo void, como
mostrado aqui:
void *ponteiro_memoria;

7.19 Ponteiros para as Funes


A Linguagem C permite criar ponteiros para todos os tipos de dados. Alm disso, ela
permite que os programas criem e usem ponteiros para as funes. O uso mais comum
dos ponteiros para funes permitir que os programas passem uma funo como um
parmetro para outra funo. As seguintes declaraes criam ponteiros para funes:
int (*min)();
int (*max)();
float (*media)();

Observe o uso dos parnteses entre os nomes das variveis. Se os parnteses


fossem removidos, as declaraes serviriam como prottipos de funo para as funes
que retornam ponteiros para um tipo especfico, como mostrado aqui:
int *min();
int *max();
float *media();

Ao ler uma declarao de varivel, deve-se comear com a declarao mais


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

7.20 Ponteiro para uma Funo


O uso mais comum de um ponteiro para uma funo passar essa funo como
um parmetro para outra funo. O programa a seguir passa a funo min ou max para a
funo pega_result. Dependendo da funo que o programa passa, o valor que
pega_result retorna ser diferente:
#include <stdio.h>
int pega_result(int a, int b, int (*compare)())

{
return(compare(a, b));

// Chama a funo 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_result(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);
}

7.21 Usando um Ponteiro para um Ponteiro para um


Ponteiro
A Linguagem C permite criar variveis que so ponteiros para outros ponteiros.
Em geral, no h limite no nmero de indirees (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 confuso considervel, e tornar seus
programas muito difceis de compreender. Por exemplo, o programa a seguir usa trs
nveis de ponteiros para um valor do tipo int. Separe um tempo para experimentar este
programa e desenhe os nveis de indireo em um pedao 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));
}

7.22 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste
mdulo. Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo
ou mesmo direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
7.1 Ponteiros como Endereos: visto que um ponteiro uma
varivel ou um valor que contem um endereo.
7.2 Determinando o Endereo de uma Varivel: foi visto como
obter um endereo de uma varivel e quando os programas precisarem determinar o
endereo de uma varivel, devero usar o operador de endereo da Linguagem C &.
7.3 Como a Linguagem C trata Matrizes como Ponteiros:
mostrado o cdigo de um programa que exibe o endereo inicial de vrias matrizes
diferentes.
7.4 Aplicando o Operador de Endereo (&) a uma Matriz: foi
visto que se o operador de endereo for aplicado a uma matriz, a Linguagem C retornar
o endereo inicial da matriz.
7.5 Declarando Variveis Ponteiros: 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 varivel.
7.6 Desreferenciando um Ponteiro: foi explicado que desreferenciar
um ponteiro o processo de acessar o valor de uma posio de memria especfica. Para
desreferenciar o valor de um ponteiro, usa-se o operador asterisco de indireo (*).
7.7 Usando Valores de Ponteiro: foi apresentado o cdigo de um
programa em que o valor de um ponteiro usado para receber o endereo de uma

varivel de depois o ponteiro usado para indicar o valor armazenado na posio de


memria que ele indica.
7.8 Ponteiros com Parmetros de Funo: foi visto que quando for
necessrio alterar o valor de um parmetro, dever passar para a funo um ponteiro
para um parmetro. Foi apresentado um programa que usa os ponteiros para dois
parmetros do tipo int para permutar os valores das variveis.
7.9 A Aritmtica de Ponteiros: foi explicada de manira clara a
aritmtica de ponteiros, que trata os ponteiros como valores que podem ser somados ou
subtrados.
7.10 Incrementando e Decrementando um Ponteiro: foram vistas
as operaes de incremento e o decremento do valor de um ponteiro, que servem para
apontar para a prxima posio ou para a posio anterior na memria.
7.11 Percorrendo uma String usando um Ponteiro: foi visto um
programa que usa uma funo para exibir uma string de caracteres usando um ponteiro.
7.12 Funes que retornam Ponteiros: foi explicado que o valor
que uma funo retorna sempre do tipo declarado no prottipo ou cabealho da
funo. Alm de retornar esses tipos bsicos, as funes podem declarar ponteiros para
os valores.
7.13 Criando uma Funo que retorna um Ponteiro: foi visto um
programa que cria uma funo que converte todos os caracteres de uma string para
maisculas e depois retorna um ponteiro para uma string.
7.14 Uma Matriz de Ponteiros: foi explicado que assim como podese criar funes que retornam ponteiros, tambm pode-se criar matrizes de ponteiros.
Mais comumente sero usadas matrizes para conter strings de caracteres.
7.15 Percorrendo em um Lao uma Matriz de Strings de
Caracteres: foi visto um programa que percorre em um lao uma matriz , que contm
ponteiros para strings que contm os nomes dos dias da semana.
7.16 Usando um Ponteiro para um Ponteiro para String de
Caracteres: foi visto um programa que usa um ponteiro para um ponteiro para string de
caracteres para exibir o contedo de uma matriz.
7.17 Declarando uma Constante String usando um Ponteiro: foi
visto como declarar uma constante string usando um ponteiro.
7.18 O Ponteiro do tipo Void: foi dada uma explicao geral sobre o
ponteiro do tipo void.
7.19 Ponteiros para as Funes: foi visto que a Linguagem C
permite que os programas criem e usem ponteiros para as funes.
7.20 Ponteiro para uma Funo: foi visto que o uso mais comum de
um ponteiro para uma funo passar essa funo como um parmetro para outra
funo.
7.21 Usando um Ponteiro para um Ponteiro para um Ponteiro: foi
visto que a Linguagem C permite criar variveis que so ponteiros para outros
ponteiros. Em geral, no h limite no nmero de indirees (ponteiros para ponteiros)
que os programas podem usar.