11/10/12
Página de Evy Salcedo
Física Computacional ­ FSC­5705
Súmula
Aulas
Lista
Conc.
Freq.
Outros
Ensino
Estrutura de um programa em C
01
02
03
04
05
06
07
08
09
10
#include <stdio.h>
int main(void){
/* A linha embaixo imprime na tela */
printf("Ola, mundo\n");
return 0;
}
[usuario@pclabfis: ]# gcc exemplo01.c ­o exemplo01 ­std=c99
[usuario@pclabfis: ]# ./exemplo01
Ola, mundo
Na aula anterior mostramos o nosso primeiro programa escrito em C. Esse primeiro programa,
que imprime a frase ola, mundo, foi escrito para dar seguimento à tradição introduzida por Brian
Kernighan no seu livro "The C Programming Language" o qual é um livro de referencia para
programação em C. Na figura acima reproduzo o programa ao qual me refiro a fim de analisar a
estrutura dos programas em C.
Na primeira linha temos uma diretiva que é lida pelo preprocessador do compilador. Essa diretiva
informa ao compilador que inclua o conteúdo do arquivo de cabeçalho stdio.h (o .h vem de
header que significa cabeçalho). Nesse arquivo estão as definições das funções que dizem
respeito a entrada e saída de dados do programa, como por exemplo a função printf utilizada
para imprimir na tela, outras funções tratam de saída de outros dispositivos, como o HD do
computador (salvar no HD).
Todo os programas em C são constituídos por uma o mais funções. A principal de essas funções
é a função main (que se traduz literalmente como principal). O código associado a essa função é
contido em um bloco de código. Cada bloco é delimitado por um par de chave: { para abre o
bloco, e } para fechar o bloco. Quando um programa é executado o sistema operacional procura
a função main para executar o seu código (delimitado pelas chave).
A palavra reservada int colocada antes do main diz para o compilador que deve informar ao
sistema operativo esperar um retorno do tipo inteiro da função main quando esta termine. Uma
outra opção seria utilizar void (que significa vazio) no lugar do int, em esse caso o sistema
operativo não esperaria uma resposta e não seria necessário colocar return da linha 8 .
Os parenteses, ( e ), depois da palavra main é onde são colocadas as variáveis que receberam
possíveis dados de entrada para a função main. Em especial a função main admite dois variáveis
de entrada, tradicionalmente são nomeados de argc e argv. A essas variáveis se lhes chama
argumentos da função, em um aula futura trataremos em detalhe os argumentos das funções.
Neste exemplo não esperamos nenhum dado de entrada e por isso utilizamos o palavra
reservada void para informar que não é necessário esperar por dados (dai que se use void que
significa vazio).
No corpo (bloco) da função temos três linhas. Na linha 5 temos um comentário. Comentários
são pedaços do código que não são interpretados pelo compilador. Um comentário se da inicio
com /* e termina com */. Com o advento do C++ uma outra forma de comentário foi
introduzida o barra-barra, //, mas a diferença do anterior o barra-barra só comenta a linha onde
foi colocado enquanto que o /* */ comenta tudo o que estiver dentro do operador (varias
linhas, até)
/media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula104.html
1/6
11/10/12
Página de Evy Salcedo
Na linha 6 é utilizada a função printf cujas definições estão dentro do cabeçalho stdio.h. Essa
função permite imprimir o valor de uma variável no terminal. Ela admite um ou mais parâmetros
de entrada, o primeiro parâmetro pode ser uma sequencia de caráteres ou uma string de
controle que informa à função como tratar os dados de entrada, os outros argumentos são as
variáveis a serem impressas. No exemplo mostrado acima só é passado um argumento que é
uma variável de tipo carácter a qual deve ser impressa.
Na linha 8 utilizamos o comando return para devolver o resultado da função, que no caso é zero.
Observe que além da string (caráteres) a ser impressa (Ola, mundo) temos uns outros caráteres,
\n. A barra nesses caráteres se denomina de escape; escape n (ou barra n) diz para o
compilador introduzir nova lina. Além de \n temos \t (tabular), \r (retorno do carro), \a (alerta)
\\ (a barra) e \" (aspas).
Tipo de variáveis
C é uma linguagem fortemente tipada, assim todas as variáveis a serem utilizadas no programa
devem ser previamente definidas. A definição das variáveis em C segue o seguinte modelo
Tipo nome_da_variável
Onde o Tipo pode ser int, float, char. Essa definição prévia, permite que o compilador negocie
com o sistema operacional quanta memoria RAM ele vai precisar para armazenar as variáveis que
um dado programa vai utilizar. A origem disto está em que cada tipo de variável precisa de um
tamanho de memoria específico (medido em bits ou bytes).
Tipo
Tamanho
(bits)
Faixa
char
8
-127 a 127
unsigned char
8
0 to 255
short
16
-32,767 to 32,767
unsigned short
16
0 a 65,535
int
32
-2147483647 a 2147483647
unsigned int
32
0 a 4294967295
long
32
-2147483647 a 2147483647
unsigned long
32
0 a 4294967295
long long
64
-9223372036854775807 a
9223372036854775807
unsigned long
long
64
0 to 18446744073709551615
float
32
~6 dígitos de precisão
double
64
~15 dígitos de precisão
int:
armazena variáveis do tipo inteiro, por exemplo:
sem parte decimal.
,
A = 1
int A, F , g
float:
armazena variáveis com parte decimal, exemplo:
float
F = 2
,
,
g = 1000
,
i = 10.1
k = 92.4
, etc, isto é,
J = 1011.0
, etc.
i, k, J
char
armazena
caracteres,
exemplo:
′′
char M ateria =
′′
Quantic a
′′
,
2.0 ,
,
,
etc. Observe que os caracteres são definidos entre aspas duplas. Quando definida uma
′′
char C lasse =
M ecanic a
′′
′′
char C ientista =
P lanck
/media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula104.html
′′
char N umero =
′′
2/6
11/10/12
Página de Evy Salcedo
variável de tipo character devemos informar a quantidade máxima de caracteres que
′′
′′
a variável poderá assumir, assim no exemplo M ateria = Quantica temos 8
caracteres.
char
M ateria[8], C ientista[6], N umero[3]
Devemos
como em
string são
à string,
se observar que a manipulação de strings (caráteres) no C não é trivial
Fortran, por exemplo. É necessário utilizar a biblioteca string.h isto porque
vetores. Não é possível utilizar o comando de atribuição e assinar um valor
não é valido escrever simplesmente no meio do código algo como
′′
′′
M ateria =
Quantic a ,
só
é
valido
na
definição
da
variável:
′′
′′
char M ateria =
Quantic a . De forma que neste primeiro momento deixemos as
variáveis string para depois.
Além dos tipos aqui apontados existem outros que são possíveis de serem utilizados. unsigned
char, unsigned int, long int, unsigned long int, long double.
Agora sabemos que existem 4 tipos básicos no C: char, int, float, double; esses tipos podem ser
estendidos mediante o uso da biblioteca de string, da biblioteca complex para trabalhar com
números complexos ou definindo nosso proprios tipo de variáveis contudo, antes de dar esse
passo em direção à complexidade vamos entender os tipos básicos analisando um exemplo:
01
02
03
04
05
06
07
08
09
#include <stdio.h>
int main(void){
float nota01; /* declara nota01 como uma variável do tipo float */
float nota02; /* declara nota02 como uma variável do tipo float */
float total; /* declara total como uma variável do tipo float */
float media; /* declara media como uma variável do tipo float */
10 11 nota01 = 85.5; /* constante tipo float 85.5 atribuido ah nota01 */
/media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula104.html
3/6
11/10/12
Página de Evy Salcedo
12
13
14
15
16
17
18
19
nota02 = 97.0; /* constante tipo float 97.0 atribuido ah nota02 */
total = nota01 + nota02; /* resultado da soma atribuido ah total */
media = total / 2.0; /* resultado da divisao atribuido ah media */
printf("A media das notas eh %f\n", media); /* impressao em tela do valor
armazenado em media */
return 0;
}
[usuario@pclabfis: ]# gcc exemplo02.c ­o exemplo02 ­std=c99
[usuario@pclabfis: ]# ./exemplo02
A media das notas eh 91.250000
No exemplo fica claro que você primeiro define a variável e depois pode atribuir um valor a ela.
Utilizamos a palavra atribuir porque o = entre a variável e o valor constante a ser atribuído não
deve ser entendido como um igual matemático sinão como um comando (de atribuição) que
informa para colocar um dado numa determinada posição da memoria. Note que nos
comentários do programa anterior chamei de constantes de tipo float ao número que foram
assinado às variáveis.
Essa forma de declaração tem o problema de ocupar uma linha para cada variável, o C permite
definir variável do mesmo tipo na mesma linha, dessa forma o programa anterior seria reescrito
como
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
#include <stdio.h>
int main(void){
float nota01, node01, total, media;
nota01 = 85.5;
nota02 = 97.0;
total = nota01 + nota02;
media = total / 2.0;
printf("A media das notas eh %f\n", media);
return 0;
}
De fato, o C permite definir atribuir valores às variáveis no momento da definição:
01
02
03
04
05
06
07
#include <stdio.h>
int main(void){
float nota01 = 85.5, node01 = 97.0, total, media;
08
09
10
11
12
13
14
total = nota01 + nota02;
media = total / 2.0;
printf("A media das notas eh %f\n", media);
return 0;
}
Conversão de tipo
Para converter uma variável de um tipo numa de outro tipo simplesmente atribuímos essa
variável à outra do tipo diferente ou podemos utilizar a operação chamada de cast. Para realizar
um cast simplesmente colocamos à frente da variável o tipo a que desejamos converter ela entre
parenteses, por exemplo suponhamos que a variável a seja do tipo int, a operação de cast b =
(float) a é tal que o valor da variável a é convertido em float e assinado à variável b.
01 #include <stdio.h>
02 03 int main(void){
/media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula104.html
4/6
11/10/12
Página de Evy Salcedo
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
int i1, i2;
float f1;
i1 = 1;
i2 = 2;
f1 = i1 / i2;
printf("f1 = %f\n", f1);
f1 = (float) i1 / (float) i2;
printf("f1 = %f <‐‐‐casting\n", f1);
return 0;
}
[usuario@pclabfis: ]# gcc exemplo03.c ­o exemplo03 ­std=c99
[usuario@pclabfis: ]# ./exemplo03
f1 = 0.000000
f1 = 0.500000 <­­­casting
No exemplo de acima vemos que na linha 12 é realizada uma divisão de duas variáveis inteiras e
o resultado é armazenado na variável f1. Note que como resultado dessa operação é impressa
na tela o valor de 0.000000 e não de 0.500000, como é esperado. A razão disso é que como foi
realizada uma operação com inteiros o resultado dessa operação é um inteiro que é atribuído a
um float. Para correger o problemas devemos realizar um cast das variáveis, isso é feito na linha
16 onde cada variável é promovida para float, nesse caso o resultado é o esperado.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
int main (void){
int i1;
float f1;
double d1, d2;
d1 = 1.947288475921421; /*15 numeros depois do ponto*/
printf("d1 = %.15f\n", d1);
f1 = d1;
printf("f1 = %.15f <‐‐ truncada na VI casa decimal\n", f1);
i1 = f1;
printf("i1 = %.15f <‐‐ formato errado\n", i1);
printf("i1 = %d <‐‐ truncada parte decima\n", i1);
return 0
}
[usuario@pclabfis: ]# gcc exemplo04.c ­o exemplo04 ­std=c99
exemplo04.c: Na função 'main':
exemplo04.c:20: aviso: format '%.15f' expects type 'double', but argument 2 has type 'int' [usuario@pclabfis: ]# ./exemplo04
d1 = 1.947288475921421
f1 = 1.947288513183594 <­­ truncada na VI casa decimal
i1 = 1.947288513183594 <­­ formato errado
i1 = 1 <­­ truncada parte decima
No exemplo acima se mostra os cuidados que devem ser tomados no caso de conversão de
tipos. Nesse exemplo é definida uma variável de dupla precisão d1 onde é atribuído o valor
contante 1.947288475921421 (C trata todos os valores contantes que possuem parte decimal
como doubles, diferente do fortran que os trata como float.). O valor dessa variável é impresso
/media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula104.html
5/6
11/10/12
Página de Evy Salcedo
na tela, repare que foi solicitado à função printf imprimir 15 números depois do ponto utilizando o
formato: %.15f. Depois atribuímos o valor da variável double a uma variável float,
consequentemente o compilador de C fará uma conversão de tipo. A fim de verificar isso
pedimos para o imprimir na tela o valor da variável float e se observe que até a VI casa decimal o
valor do float coincide com o do double, além dessa posição os números divergem. De onde
saem esse números extra? A origem deles está no fato de que computadores trabalham na base
2 e nos tratamos de representar um número da base 10 (nossa base diária) na base 2. Depois
atribuímos o valor a uma variável do tipo inteira e mandamos imprimir na tela, mantendo a
formatação de float, note que o resultado está errado. Para corrigir deve ser mudado o
especificado de formato para %d, como é feito na linha 22.
Conversões entre tipos de dados sempre envolvem perda de informação, de alguma forma. É
necessário prestar atenção a esses fatos o podemos obter resultados desastrosos. Como
exemplo desse tipo de calamidades cito o problema do Ariane 5 e do sistema de misseis patriot.
No primeiro caso era convertido um double para um int, quando o double era 32768.alguma
coisa a conversão resultou em outro número que não era 32768, isso porque o int vai até
32767. No caso do sistema Patriot foi o fato do tempo ser medido em decimas de segundo: 1.0
/ 10.0, em binário esse numero é igual a 0.0001100110011001100110011001100 … o problema
foi que esse numero era armazenado num float (de 24 bits) assim representava o número como
0.00011001100110011001100
o
que
introduzia
um
erro
de
0.0000000000000000000000011001100 … que é em decimal 0.000000095, assim, depois de 100
horas de ligado o sistema o erro aumentava para 0.34 segundos e resultava no calculo errado da
trajetória.
/media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula104.html
6/6
Download

Física Computacional FSC5705