Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Declarao de apontadores
Um apontador em C nada mais do que uma varivel comum, em cujo contedo
armazenamos o endereo de memria de um outro objeto. O objeto cujo endereo
armazenado pode ser de qualquer tipo, como, por exemplo, uma outra varivel, um
vetor, ou mesmo uma funo. como se a varivel apontasse para o objeto cujo
endereo est ali armazenado (da o nome).
Um apontador, sendo uma varivel, deve tambm ser declarado. Tambm devemos
declarar o tipo do objeto cujo endereo o apontador armazena. Uma vez declarado, o
apontador s deve conter endereos de objetos desse tipo. Conhecendo o tipo do
objeto cujo endereo o apontador armazena vai nos permitir escrever certos tipos de
operaes, ditas de aritmtica com apontdores, e cujos resultados dependem do tipo
do objeto. Assim, preciso conhecer o tipo do objeto para o qual o apontador aponta.
Examinaremos esses operadores mais adiante.
Para declarar uma varivel de tipo apontador, iniciamos a declarao, como sempre,
indicando um tipo. Este ser o tipo dos objetos para os quais a varivel poder
legalmente apontar. Logo em seguida, declaramos o nome da varivel que ser o
apontador. Porm, para indicar que essa varivel um apontador (e no uma varivel
comum do tipo declarado) precedemos seu nome pelo smbolo * na declarao.
12/4/2010 15:01 1
Atribuindo para variveis de tipo apontador
Apontadores armazenam endereos de outros objetos. Portanto, deve haver uma
maneira de se obter endereos de objetos em C. Para isso, usamos o operador &.
Quando aplicado sobre uma varivel, o operador & devolve o endereo na memria
dessa varivel.
Por exemplo, considere
float x=-1.0f;
float *p;
p = &x;
12/4/2010 15:01 2
uma de suas variveis. No confunda este mecanismo com a memria virtual, que
apenas uma maneira do sistema operacional, com a ajuda de espao em disco,
articialmente estender o espao de endereos de memria disponveis alm da
capacidade fsica da memria principal do computador.
Podemos (mas provavelmente no devemos), tambm atribuir valores negativos
varivel p.
Considere o seguinte trecho de cdigo:
Uma varivel inteira, uma fracionria, dois apontadores para int e trs apontadores
para double.
printf("Tamanho de um int: %1d bytes, e de um double = %1d bytes\n",
sizeof(int),sizeof(double));
printf("Tamanho de um apontador para ints: %1d bytes, e para doubles:
%1d bytes\n\n",sizeof(int *),sizeof(double *));
p=&i; p2=p+1;
f=&x; f1=f+1; f2=f-2;
12/4/2010 15:01 3
Imprimimos os valores dos apontadores. Note o modificador %p. Este modificador se
aplica a resultados de expresses que denotem endereos de memria. Os valores
impresos na sada estaro codificados na base hexadecimal. O resultado impresso,
numa rodada na minha mquina foi
confirmando a discusso.
12/4/2010 15:01 4
conhecido como designando uma varivel de tipo float, e, portanto, j tem um
endereo designado que pode ser obtido pelo emprego do operador &.
Para entender a atribuio e o uso do operador *, vamos assumir que o endereo
atribudo a x seja 500. Note que p foi ento inicializada com o valor 500. Na
atribuio, o valor retornado pela expresso (* p) no o valor armazenado na
varivel p. Isto seria 500, ou seja, seria o endereo da varivel x. A expresso (*p)
retorna, isto sim, o contedo da posio de memria cujo endereo est armazenado
em p. Portanto, (*p) deve retornar o contedo armazenado na posio de memria
cujo endereo 500, ou seja, retorna o valor armazenado em x, que -1.0. E este
justamente o valor armazenado na varivel para a qual p aponta. O espao entre o
smbolo * e o nome da varivel p no obrigatrio, nem os parnteses envolvendo a
expresso (* p) so obrigatrios. Eles esto l por clareza. Os operadores & e * so
unrios e tm precedncia sobre operadores binrios.
O resto da expresso calculado normalmente, e o valor final, -4.0, armazenado
na varivel y.
Nesse mesmo exemplo, se omitirmos o smbolo *, a atribuio ficaria na forma
y = p + 5.0f;
p = 0xaaa;
y = (float)(* p)+5.0f;
Duas situaes podem ocorrer. Por uma coincidncia fortuita, o endereo 0xaaa
vlido, isto , estava alocado para esse programa nesse momento; o computador
recolhe o que estava neste endereo, transforma este valor para um float (por
causa do "cast" para float), adiciona 5.0f e armazena o resultado na varivel y.
Ou ento o endereo 0xaaa no est alocado para esse programa nesse momento,
isto , invlido (como seria com certeza se fizssemos p = -0xaaa), e a
obteramos um erro de execuo, pois o computador no teria como acessar o
endereo indicado e seu contedo para calcular o valor da expresso. Em qualquer
hiptese, um aviso de compilao seria provavelmente emitido, alertando que a
atribuio p = 0xaaa pode causar problemas.
12/4/2010 15:01 5
(*p) = . . .
Vamos assumir que nessa execuo o endereo atribudo a x seja 500. Portanto, o
apontador p conter 500. O valor da expresso direita, na linha 2, 5.0f. Este
valor dever ser armazenado na varivel cujo endereo que est contido em p, ou seja,
na varfivel cujo e endereo 500. Mas 500 o endereo da varivel x, pois
inicializamos p atribuindo-lhe o endereo de x, na forma &x. Portanto, o efeito da
atribuio ser armazenar o resultado 5.0f na varivel x.
Valem as mesmas observaes colocadas acima, se atribumos um valor arbitrrio
para o apontador p e, em seguida, tentamos usar (*p) esquerda de uma atribuio.
Se, por acaso, o endereo que atribuirmos resultar vlido, o comando executado,
armazenando o valor calculado para a expresso direita da atribuio =, no endereo
que atribumos a p. Se o endereo no for vlido, obtermos um erro durante a
execuo do programa.
Vamos agora examinar outro trecho de cdigo.
Informa os valores contidos nas variveis. Note que os apontadores ainda no foram
inicializados e, portanto, agora ainda contm valores arbitrrios. Alguns compiladores
inicializam variveis declaradas com um valor padro (por exemplo, zero).
Continuando,
p=&i; f=&x;
*f = sqrt(*p)+1.0;
*p = (int)(*f) - 3;
12/4/2010 15:01 6
printf("Val p = %p, val f = %p\n",p,f);
printf("Val i = %d, val x = %f\n",i,x);
3.1622. . . .
4.1622 . . .
que deve ser armazenado na varivel indicada no lado esquerdo da atribuio, no caso
(*f). Ento, o valor contido em f tomado como um endereo e, neste endereo,
devemos armazenar o valor calculado. Como f contm o endereo de x, o resultado
final, 4.1622. . ., armezenado em x (aps ser silenciosamente convertido para um
float por outro cast implcito).
A terceira linha ilustra uma situao semelhante. O valor apontado por f
convertido em um int (pelo cast), resultando em 4. Subtramos 3, obtendo 1.
Este valor armazenado no endereo apontado por p. Como p contm endereo de i,
armazenamos 1 na varivel i. As duas ltima linhas devem confirmar que o valor dos
endereos armazenados em p e f no devem se alterar, enquanto que os valores
contidos em i e x, que so as variveis apontadas por p e f, devem sofrer as
alteraes previstas. Finalmente,
*q=i+1; /* PERIGO !! */
x=(*e)-1.0; /* PERIGO !! */
printf("Val i = %d, x = %f\n",i,x);
printf("Val (*q) = %d, val x = %f\n",*q,x); /* PERIGO !! */
12/4/2010 15:01 7
Lendo tipos complexos
A linguagem C suporta vetores, funes e apontadores. Com esses objetos podemos
usar, respectivamente, os operadores [ ], ( ) e *. Combinando esses operadores
entre si, podemos construir outros tipos bem mais complexos em C.
Declaraes mais complexas em C sempre causam problemas de interpretao e so
potenciais focos de erros. Para dominar a construo e a interpretao de declaraes
mais complexas em C, h duas regras bsicas que devem ser conhecidas: a regra de
precedncia entre os operadores de tipos e a regra para agrupamentos entre eles.
Quanto precedncia, os operadores para construir vetores e funes tm a mesma
precedncia. Alm disso, ambos tm precedncia sobre o operador que designa
apontadores. Assim, a hierarquia de precedncia fica na forma
Precedncia alta: [ ], ( )
Precedncia baixa: *
Note que sempre podemos usar os parnteses para impor outra ordem de precedncia,
como feito em expresses aritmticas comuns.
int x[ ]( )
seria agrupado da esquerda para a direita, resultando em
int ( x[ ] )( )
onde o primeiro par de parnteses serve de agrupador e o segundo par indica funo.
Ento, a varivel x est sendo declarada como um vetor de funes que retornam
inteiros. No caso do operador *, a declarao
int **p
int *(*p)
Sempre devemos analisar uma declarao em C partindo do nome da varivel que est
sendo declarada e, obedecendo as regras de precedncia e agrupamento, a cada passo
envolver mais operadores, terminando por esgotar a declarao toda.
A melhor forma de se adquirir experincia na anlise de declaraes mais complexas
em C, estudar alguns exemplos tpicos. Nos casos abaixo, as duas regras descritas
acima so sempre seguidas risca. Alm disso, usamos o tipo primitivo int em
12/4/2010 15:01 8
todas as declaraes. Deve ficar claro, porm, que o tipo int poderia ser substitudo
por qualquer outro tipo j definido pelo programador.
Nos prximos exemplos, iremos progredindo sistematicamente na direo de tipos
mais complexos. Repare que algumas combinaes dos operadores produzem tipos
invlidos, que no so suportados pelo compilador C.
int x;
Varivel x declarada como de tipo inteiro.
int *x;
Varivel x declarada como um apontador para um inteiro.
int x[ ];
Varivel x declarada como um vetor que contm inteiros.
int x( );
Varivel x declarada como uma funo que retorna um inteiro.
int *x[ ];
Varivel x declarada como um vetor que contm apontadores para inteiros.
Equivalente a
int *x( );
Varivel x declarada como uma funo que retorna um apontador para inteiro.
Equivalente a
int x[ ]( );
Varivel x declarada como um vetor onde cada posio contm uma funo
que retorna um inteiro. Equivalente a
Mas, essa declarao resulta num erro de compilao, pois vetores de funes
no so suportados em C. Isto razovel, visto que o tamanho do cdigo de
cada funo varivel, ou seja, heterogneo, indo contra a noo de vetores,
que agrupam apenas objetos homogneos.
int x( )[ ];
Varivel x declarada como uma funo que retorna um vetor de inteiros.
Seria equivalente a
12/4/2010 15:01 9
Mas essa declarao tambm resulta num erro de compilao, pois funes
no podem retornar vetores em C. Isto razovel, pois no poderamos atribuir
o resultado retornado. Lembre que no h atribuio direta de um vetor para
outro em C.
int x[ ][ ];
Varivel x declarada como um vetor onde cada posio contm um segundo
vetor de inteiros. Equivalente a
int x( )( );
Varivel x declarada como uma funo que retorna uma segunda funo que,
por sua vez, retorna um inteiro. Equivalente a
int *x[ ]( );
Equivalente a
Varivel x declarada como um vetor onde cada posio contm uma funo
que retorna um apontador para um inteiro. Causa erro de compilao, pois
no temos vetores de funes em C.
int *x( )[ ];
Equivalente a
Varivel x declarada como uma funo que retorna um vetor onde cada
posio contm um apontador para um inteiro. Causa erro de compilao,
pois no temos funes que retornam vetores em C.
int *x[ ][ ];
Equivalente a
12/4/2010 15:01 10
int *x( )( );
Equivalente a
Varivel x declarada como uma funo que retorna uma segunda funo que,
por sua vez, retorna um apontador para um inteiro. Causa um erro de
compilao, pois funes em C no podem retornar (o cdigo de) outras
funes.
int (*x)[ ];
Parnteses usados para quebrar a regra de precedncia natural. Varivel x
declarada como um apontador para um vetor de inteiros.
int (*x)( );
Parnteses usados para quebrar a regra de precedncia natural. Varivel x
declarada como um apontador para uma funo que retorna um inteiro.
int **x;
Equivalente a
int *(*x);
12/4/2010 15:01 11
int vet[4];
12/4/2010 15:01 12
Se o ndice invlido for calculado dinmicamente (por exemplo, atravs de uma
expreso que contm variveis), o erro poder se tornar intermitente e difcil de
detectar, o que o transforma em um erro ainda mais difcil de ser caado e eliminado.
Portanto, cuidado com os ndices e lembre que o primeiro zero, no um.
Quando declaramos um vetor, por exemplo, na forma
char v[4];
o que o compilador C faz criar uma constante de nome v, com tipo char* (um
apontador para caractere), e inicializa esta constante com o endereo do primeiro
elemento do vetor. Suponha que os endereos de memria alocados para o vetor
comecem na posio 101. A declarao, na verdade, cria uma constante de nome v e
inicializa seu contedo com 101. Os demais elementos do vetor esto nos endereos
102, 103 e 104 (lembre que cada caractere ocupa um byte na memria). Note que
v se comporta como uma varivel de tipo apontador para char, com a exceo de
que no podemos atribuir para ela. Em particular, v tambm ocupa espao na
memria. Suponha que o endereo de v seja 500.
A notao v[4] na declarao apenas uma forma natural de se informar o nome do
vetor e seu tamanho. A partir da declarao, o compilador sabe que deve criar a
constante v, reservar 4 bytes de memria e atribuir a v o endereo do primeiro byte
reservado.
Podemos tambm inicializar o vetor, j no momento da declarao. Para isso, basta
listar os elementos do vetor, em ordem, separando cada dois componentes por uma
vrgula e incluindo a lista entre { e }. Assim,
int v[5] = { 0, 1, 2 };
Vetores e apontadores
Consire de novo a declarao
int vet[4];
12/4/2010 15:01 13
Na verdade, quando encontra uma expresso na forma v[i+3], por exemplo, o
compilador a substitui por *(v+(i+3)). Este mecanismo, de percorrer o vetor
usando apontadores, muito til em vrias situaes.
Note que o nome v declarado como uma constante. Ento, no ser permitido
atribuir outro valor para v (mesmo porque isso poderia levar perda do endereo real
de v[0]).
Vamos agora examinar mais alguns trechos de cdigo, para ilustrar como percorrer
vetrores atravs de apontadores.
char v[ ] = {'Z','M','T','A'};
char *c;
Tamanho de v = 4 bytes
12/4/2010 15:01 14
O contedo de v[3] confere com o ltimo caractere no vetor. O contedo de v[4],
entretanto, est uma posio alm do vetor. No se pode prever o que vir como
resposta aqui. Em seguida:
c=v;
printf("\n*(c+2) = %c\n",*(c+2));
*(c+2) = T
*(v+2)='X';
*c='Y';
printf("v[0] = %c, v[1]= %c, v[2]= %c, v[3] = %c\n", v[0], v[1], v[2],
v[3]);
Vemos que v[0] mudou para Y devido segunda atribuio, e v[2] mudou para
X, por conta da primeira atribuio.
Exemplo
O prximo exemplo implementa o mtodo da peneira para listar todos os nmeros
primos at um limite estabelecido (um nmero primo se for pelo menos 2 e se for
divisvel de maneira exata apenas por 1 e por si mesmo).
O mtodo funciona assim: construimos um vetor de inteiros onde armazenamos 1 em
toda as posies. Em seguida, fazemos vrias passadas pelo vetor, eliminando as
posies que no correspondem a nmeros primos. Eliminar uma posio significa
colocar zero naquela posio do vetor. Ao final, as posies que no forem eliminadas
correspondero aos primos procurados (i.e., para listar todos os primos, basta
imprimir as posies do vetor, de 2 em diante, que contm 1).
A cada passada, comeamos com uma posio inicial, inic. Partindo de inic+1,
percorrremos todo o resto do vetor, eliminando as posies que so mltiplos de
inic. Isso feito, posicionamos inic na prxima posio ainda no eliminada e
repetimos o ciclo.
Quando o cilclo termina? Podemos terminar quando inic ultrapassar a raz
quadrada do limite onde queremos chegar. Isso porque se um nmero tem um fator
(que no 1 nem o prprio nmero), ento tambm tem um fator que , no mximo,
igual a raz quadrada do nmero (ele no pode ter dois fatores maiores que sua raz
quadrada pois o produto destes dois fatores j resultaria maior que o prprio
nmero!). Iniciamos o cdigo com
#include <math.h>
#define MAX 10000
#define MAX_LINHA 50
12/4/2010 15:01 15
Incluimos o arquivo math.h pois vamos precisar da funo sqrt. O identificador
MAX representa o maior intervalo com o qual o programa pode lidar. J MAX_LINHA
o mximo nmero de caracteres numa linha de sada, para quando formos imprimir
a listagem dos primos encontrados.
As variveis inic, fim e limite so locais na funo main e seviro para marcar
posies no vetor. A varivel i auxiliar.
Pede um limite para o intervalo de procura (de onde vai extrair todos os nmeros
primos). O lao garante que teremos este limite (na varivel de nome tambm
limite) entre 2 e MAX. Se o usurio entrar com dado invlido, o programa pede
outro dado, at que o limite esteja no intervalo indicado.
for(i=2;i<=MAX;i++) p[i]=1;
fim=(int)sqrt( (double) limite);
Este trecho inicializa o vetor (com todas as posies ativas) e armazena na varivel
fim o maior fator que teremos que considerar. Repare no "cast" para converter o tipo
double retornado pela funo sqrt para um int. O valor inicial de inic j foi
colocado em 2.
do {
if (!p[inic]) continue;
peneira(p,inic,limite);
} while (++inic<=fim);
12/4/2010 15:01 16
Repare no if. Se a posio inic j contiver um zero, ento j foi eliminada e no
precisamos mais eliminar seus mltiplos (eles tambm j foram eliminados em
alguma passada anterior). O comando continue faz com que o programa desvie
direto para a condio de teste do lao (no caso, a condio associada ao while),
ignorando os outros comandos deste ponto at o fim do lao. No caso, isso faz com
que o programa ignore a chamada da rotina peneira e passe direto para a condio
de teste.
Na condio de teste, o valor de i primeiramente incrementado. Em seguida,
testamos se ainda no ultrapassamos o maior fator a considerar. Se ainda no, o lao
executa de novo; caso afirmativo, o lao termina.
Esta estratgia implementa o mtodo da peneira.
12/4/2010 15:01 17
A rotina imprimevals inicia calculando o nmero de dgitos que h no valor
armezenado em limite. Esta informao ser usada para auxiliar na impresso dos
resultados, formando colunas alinhadas. Este nmero armazenado na varivel nc
que, aps o for, tem seu valor incrementado para permitir um espao entre uma
coluna e a seguinte. Na varivel ncol calculamos o nmero de colunas numa linha,
usando MAX_LINHA como um limite da exteno de uma linha.
for(i=2;i<=limite;i++) {
if (*(v+i)) {
printf("%*d",nc,i);
if (col==ncols) {col=1; printf("\n");
}
else col++;
}
Este lao for percorre o vetor, imprimindo as posies onde h um valor no nulo.
Note o modificador %*d na funo printf. Este modificador sinaliza que o
prximo argumento do printf ser usado no lugar do smbolo *, de modo que
podemos controlar o nmero de casas para a impresso do argumento na lista de sada
deste printf. No caso, usamos sempre nc como o nmero de casas a ocupar,
garantindo ento que as colunas estaro alinhadas.
Aps imprimir cada valor, o segundo if testa se j imprimimos ncol colunas nesta
linha. Se for este o caso, acrescentamos um caractere de fim-de-linha e
reposicionamos o contador col em 1. Caso contrrio, basta incrementar col,
indicando que estaramos usando mais uma coluna desta linha.
int x[10];
printf("%d\n",x[0]);
printf("%d\n",*x);
12/4/2010 15:01 18
ambos resultando na impresso do valor armazenado na primeira posio do vetor x.
Quando o nome do vetor ocorre isoladamente, i.e., sem estar associado ao operador
[ ], que indica uma posio indexada, o compilador interpreta esse nome como um
apontador para o primeiro endereo de memria do vetor. Por exemplo, junto com a
declarao
int *pi;
a seqncia de comandos
pi=x;
printf("%d, %d\n",*pi,pi[0]);
printf("%p, %p\n",pi,&pi);
produz valores distintos. Ocorre que o nome x no exatamente uma varivel como
pi. Esta ltima uma varivel usual, com uma posio de memria reservada para
si e, portanto, com um endereo de memria nico onde so armazenados os valores
atribudos a pi . O nome x, que designa um vetor, tratado de uma forma
diferenciada pelo compilador. Por isso, o endereo de x resulta tambm no mesmo
valor que o endereo do objeto apontado por x (que o primeiro endereo na
memria onde esto armazenados os valores do vetor), o que no ocorre com pi, por
exemplo.
Devemos lembrar tambm que, embora o nome x possa ser encarado como um
apontador para int, ele representa uma constante, i.e., no podemos atribuir novos
valores para x. Assim, a atribuio
x=pi;
12/4/2010 15:01 19
que introduz soma como uma funo que recebe dois argumentos de tipo int e
retorna outro valor de tipo int. Assuma tambm a declarao de varivel
int (*f)( );
que introduz f como um apontador para uma funo que retorna um int. Se
executssemos o comando
f=soma;
printf("%p, %p, %p, %p\n",soma,&soma, f, &f);
obteramos os mesmos valores que anteriormente, exceto pelo terceiro deles. Agora, o
valor armazenado em f resulta da avaliao da expresso soma. Como no usamos
o operador ( ), que foraria a execuo do cdigo da funo f, o compilador
interpreta como uma referncia ao nome soma, retornando um apontador (i.e. o
endereo) da funo soma. Portanto, os trs primeiros valores impressos sero agora
idnticos. O ltimo ainda indica o endereo da varivel f.
O comando
printf("%d, %d\n",soma(2,3),f(4,5));
printf("%d, %d\n",(*soma)(2,3),(*f)(4,5));
f=**soma;
12/4/2010 15:01 20
printf("%d, %d\n",(*soma)(2,3),(****f)(4,5));
Exemplo
Considere o cdigo C:
int x[10]={100,2,3,4,5,6,7,8,9,0};
int *pi;
printf("%d, %d\n",x[0],(*x));
pi=(int *)(&x);
printf("%p, %d, %d\n",pi,*pi,pi[0]);
printf("%p, %p, %p\n",&x[0],x,&x);
printf("%p, %p\n",pi,&pi);
Podemos passar um nome de funo como argumento para outras funes em C. Isso
possibilita um mecanismo flexvel, onde a funo que entra como argumento pode ser
trocada a cada invocao da funo mestre.
Uma declarao de funo na forma
12/4/2010 15:01 21
declara f como uma funo que recebe dois argumentos e retorna um int. O
segundo argumento uma varivel de tipo int. O primeiro argumento uma funo
que recebe um int e retorna um double.
Lembre que o compilador trata nomes de funes como apontadores para endereos
de memria. Assim, essa declarao seria equivalente a
onde est claro que g um apontador para uma funo que recebe um int e
retorna um double.
O mtodo de Newton um algoritmo eficiente para se achar razes de funes
(contnuas). Se f uma funo, uma raz de f todo valor x onde f se anula,
isto , f(x)=0.
Note que, se num ponto temos f(a) > 0, e se num outro ponto b mais adiante
temos f(b) < 0, ou seja f(a) e f(b) tm sinais trocados, ento f deve se anular
em algum ponto intermedirio entre a e b. O mtodo de Newton determina um ponto
intermedirio c, entre a e b, tal que f(c) =0 (pode haver mais de um tal ponto c;
o mtodo acha um deles).
O mtodo funciona assim. Assuma que f(a) > 0 e que f(b) <0. Calculamos o
ponto intermedirio m=(a+b)/2. Se f(m) = 0, o ponto m a raz desejada. Se
f(m) > 0 ento a raz deve estar entre os pontos m e b, visto que f(m)>0 e
f(b)<0 indicam a presena de uma raz entre m e b. Caso contrrio, a raz est
entre a e m. Em qualquer hiptese, o intervalo onde se encontra a raz foi dividido
metade. O processo continua at que a raz seja encontrada. o mecanismo de dividir
o intervalo til de busca metade, a cada passo, que torna este mtodo muito
eficiente.
Exemplo
Considere o cdigo:
#include<math.h>
#define EPSILON 1.0E-10
double poli(double a) {
/* funcao = 3.3a^5 - 25.0a^2 + 204.5a - 18.6 */
return (3.3*a*a*a*a*a - 25.0*a*a + 204.5*a - 18.6);
}
12/4/2010 15:01 22
if (f(a)*x>0.0) a=m; else b=m;
}while (1);
return m;
}
Nesse trecho do programa principal testamos a rotina raiz sobre a funo cosseno.
Essa funo tem o valor 1 no ponto zero e o valor -1 no ponto 3.14 (em radianos).
Portanto, ela deve ter uma raz em algum ponto intermedirio. A sada
A raz est no ponto 1.5708 (em radianos). A linha seguinte confirma que a funo
calculada nesse ponto tem um valor prximo de zero (abaixo de EPSILON). Observe
os parmetros de chamada da funo raiz. O primeiro deles o nome da funo
cosseno, cos. Na execuo do cdigo de raiz, o nome do parmetro formal f
substitudo pelo nome da funo cosseno, fazendo com que, durante a execuo, a
rotina raiz use de fato a funo cosseno nos clculos, como desejado.
12/4/2010 15:01 23
Valor de poli(0.0919879) = -8.02357e-10
De novo, fica comprovado que no ponto calculado para a raz o valor da funo
prximo de zero.
12/4/2010 15:01 24