Académique Documents
Professionnel Documents
Culture Documents
Gest
ao de Programas Extensos
Bibliotecas
A Bilioteca gsl
Interface C -FORTRAN : SLATEC e LAPACK
Automatizac
ao com o GNU make
Outros t
opicos
Vtor M. Pereira
Departamento de Fsica da FCUP e Centro de Fsica do Porto
ii
iv
Conte
udo
Conte
udo
vi
Listagens
vii
Nota Pr
evia
ix
I.
Gest
ao de Programas Extensos
1
1. O modelo de compilac
ao do C
1.1. Ideias Basicas . . . . . . . . . . . . .
1.2. O modelo de compilacao em C . . .
1.3. Os passos da compilacao em detalhe
1.3.1. O pre-processador . . . . . .
1.3.2. O compilador . . . . . . . . .
1.3.3. O assembler . . . . . . . . . .
1.3.4. O linker . . . . . . . . . . . .
1.4. Linkagem est
atica e din
amica . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
3
4
6
7
8
8
10
2. Compilac
ao de m
ultiplas files
2.1. Distribuicao de c
odigo . . . . . . . . . . . . . . . . .
2.2. Criando ficheiros de objectos a partir das fontes . . .
2.3. Criando execut
aveis a partir de ficheiros de objectos
2.4. Recompilar e re-linkar . . . . . . . . . . . . . . . . .
2.5. Partilha de vari
aveis . . . . . . . . . . . . . . . . . .
2.5.1. Ambito
(Scope) . . . . . . . . . . . . . . . . .
2.5.2. Classes de armazenamento (storage classes) .
2.6. Organizacao dos dados em cada ficheiro . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
16
16
16
18
18
19
21
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3. Criac
ao de Bibliotecas
23
4. Criac
ao e gest
ao de uma Makefile
27
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
33
33
33
35
35
Conte
udo
35
39
40
5. T
opicos preliminares
5.1. O que e a gsl . . . . . . . . . . . . . . . .
5.2. Utilizacao b
asica . . . . . . . . . . . . . . .
5.3. Geradores de N
umeros Aleat
orios . . . . . .
5.4. Funcoes como argumentos . . . . . . . . . .
5.5. Funcoes de n
umero de argumentos vari
avel
5.6. A funcao gsl function . . . . . . . . . . .
.
.
.
.
.
.
43
43
43
45
47
48
50
6. Exemplos
6.1. Minimizacao de Funcoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.1. Funcional de energia livre . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.2. Inicializacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
53
53
54
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
IV. Outros T
opicos
por Vtor M. Pereira
57
7. Argumentos ao main
7.1. argv e argc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.2. Vari
aveis de ambiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
59
61
A. Lista de Comandos
65
Anexos
65
Bibliografia
67
vi
Listagens
1.1.
1.2.
1.3.
1.4.
2.1.
2.2.
2.3.
2.4.
2.5.
3.1.
3.2.
3.3.
4.1.
4.2.
4.3.
4.4.
4.5.
5.1.
5.2.
6.1.
6.2.
7.1.
7.2.
7.3.
C
odigo fonte do programa Hello World (hello.c). . . . . . . . . . . . . . . . . . .
C
odigo fonte pre-processado I (hello.i) . . . . . . . . . . . . . . . . . . . . . . . .
C
odigo fonte pre-processado II (hello.i) . . . . . . . . . . . . . . . . . . . . . . .
C
odigo fonte em assembly (hello.s) . . . . . . . . . . . . . . . . . . . . . . . . . .
C
odigo fonte do segmento main.c. . . . . . . . . . . . . . . . . . . . . . . . . . . .
C
odigo fonte do segmento hello fn.c. . . . . . . . . . . . . . . . . . . . . . . . . .
C
odigo fonte do header hello.h. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Uma alteracao local a main.c. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exemplos de
ambito de vari
aveis (scope.c). . . . . . . . . . . . . . . . . . . . . . .
Funcao bye() (bye fn.c). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Header hello2.h. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Driver para biblioteca libhello.a. . . . . . . . . . . . . . . . . . . . . . . . . . . .
Makefile para o projecto Hello World (Makefile). . . . . . . . . . . . . . . . . . .
Exemplo de c
odigo FORTRAN (twice.f). . . . . . . . . . . . . . . . . . . . . . . . . .
Exemplo de um programa em C que chama uma rotina de FORTRAN (calltwice.c).
Pr
ologo da rotina DGAUS8 do SLATEC (dgaus8.f). . . . . . . . . . . . . . . . . . . .
Exemplo de programa em C que chama a rotina DGAUS8 do SLATEC (calldgaus8.c).
Utilizacao b
asica da gsl (gsl-bessel.c) . . . . . . . . . . . . . . . . . . . . . . .
N
umeros aleat
orios com a gsl (gsl-random.c) . . . . . . . . . . . . . . . . . . . .
Definicao da entropia e energia livre para uma dada magnetizacao (minimization.c).
Programa principal (minimization.c). . . . . . . . . . . . . . . . . . . . . . . . .
Argumentos ao main() (show args.c). . . . . . . . . . . . . . . . . . . . . . . . . .
Problema 4 da folha Exerccios de linguagem C (show args.c). . . . . . . . . . .
Exemplo com vari
aveis de ambiente (environ.c). . . . . . . . . . . . . . . . . . . .
5
6
6
7
13
14
14
17
19
23
23
24
27
34
34
36
38
43
45
53
54
60
61
62
vii
Listagens
viii
Nota Pr
evia
Estas notas destinam-se primariamente aos alunos do curso de Fsica Computacional, leccionado
no departamento de Fsica da FCUP, e, por extensao, a todos quantos se interessarem pelos t
opicos
aqui aflorados. Re
une-se aqui material novo e textos ja existentes no contexto desta cadeira em
anos anteriores, preparados por alguns dos seus docentes.
Os exemplos apresentados est
ao orientados para o compilador gcc do projecto GNU (www.gnu.org),
incluindo algumas funcionalidades que, n
ao sendo embora parte do standard do C , consituem extens
oes a esse standard por parte do gcc 1 .
Ao longo do texto existem frequentes concessoes no que respeita `a utilizacao de termos de
lngua inglesa sem sobreaviso e destaque. A opcao pela utilizacao dos termos directamente na
lngua inglesa em vez da sua traducao e evidente: a quase totalidade da literatura existente nos
t
opicos abordados nestas notas e redigida nessa lngua. Seria talvez mesmo algo improdutivo
estar a introduzir traducoes para termos como assembler ou linker, os quais o leitor depois n
ao
encontraria em mais lado algum, causando confusoes desnecessarias.
Relativamente `
as convencoes, sempre que haja um comando a ser lancado na shell ele ser
a
apresentado como
$ comando
(0.1)
O elemento $ serve para identificar o texto `a sua frente como o comando a lancar e, naturalmente,
n
ao faz parte dele. Sempre que um comando devolva algum output, isso ser
a apresentado como
$ comando
linhas de output
(0.2)
(0.3)
As listagems de c
odigo fonte cujos ficheiros est
ao acessveis juntamente com este documento ser
ao
feitas dentro de caixas com devido destaque e numeracao, sendo tambem apresentado o nome do
ficheiro de c
odigo fonte ao qual a listagem se refere.
Finalmente, estas notas n
ao s
ao um produto acabado, encontrando-se em fase de desenvolvimento
e aperfeicoamento. Como tal, quaisquer coment
arios s
ao benvindos.
Vtor M. Pereira2
Porto, 25 de Maio de 2006.
1 Para
2 vmpereir@fc.up.pt
ix
Nota Previa
Parte I.
Gest
ao de Programas Extensos
por Vtor M. Pereira
1. O modelo de compilac
ao do C
1.1. Ideias B
asicas
Uma nota previa acerca de uma linguagem de programacao que e diferente da linguagem da linguagem C : a shell da GNU . Quando um comando e lancado na shell, ele e imediatamente executado.
Alem disso, a shell e ela propria uma linguagem de programacao, no sentido em que os comandos
que o utilizador escreve s
ao um programa (e que pode tambem criar um ficheiro de texto contendo
uma sequencia de comandos da shell1 ).
Por outro lado, considere o caso do C . Enquanto que um script de comandos de shell pode ser
executado directamente, um programa em C precisa de ser criado essencialmente a dois tempos:
1. Em primeiro lugar, o c
odigo deve ser escrito num ficheiro de texto simples, usando por
exemplo um editor como o emacs . Ao programa nesta forma (ao(s) ficheiro(s) de texto
contendo o c
odigo) d
a-se o nome de c
odigo fonte.
2. Depois, o c
odigo fonte necessita ser processado por um compilador que gerar
a um novo
ficheiro contendo uma traducao do c
odigo fonte numa linguagem de maquina. Este ficheiro
e chamado de execut
avel, e diz-se que o execut
avel foi compilado a partir do c
odigo fonte.
Para executar um programa compilado, em geral e necess
ario escrever o nome do execut
avel
directamente na shell. Se o execut
avel se chamar prog, ent
ao para o correr bastar
a lancar na
shell2 :
$ ./prog
(1.1)
2O
1. O modelo de compilacao do C
(1.2)
(1.3)
$ ./prog
(1.4)
Nome
filename.c
filename.i
filename.h
filename.o
filename.a
filename.so
filename.s
filename
possvel, e altamente instrutivo, efectuar cada um dos passos listados na Fig. 1.1 separada e independentemente. De seguida iremos fazer isso para o hello world, o primeiro programa tipicamente
apresentado em qualquer livro sobre C . Suponhamos que o c
odigo fonte desse programa existe num
ficheiro chamado hello.c, e que e o seguinte:
/
File hello . c
Apenas i m p r i m e a mensagem de um programa recemn a s c i d o .
V i t o r M. P e r e i r a
/
#i n c l u d e < s t d i o . h>
9
11
13
i n t main ( v o i d )
{
p r i n t f ( H e l l o , w o r l d ! \ n ) ;
return 0;
}
Listagem 1.1: C
odigo fonte do programa Hello World (hello.c).
(1.5)
$ ./hello
(1.6)
Hello, world!
(1.7)
1. O modelo de compilacao do C
1.3.1. O pr
e-processador
O primeiro passo e ent
ao invocar o pre-processador para expandir os macros e os header files. Para
executar este passo, corremos
(1.8)
(1.9)
#
#
#
#
1
1
1
1
h e l lo . c
<b u i l t i n >
<command l i n e >
h e l lo . c
10
# 1 / u s r / i n c l u d e / s t d i o . h 1 3 4
Listagem 1.2: C
odigo fonte pre-processado I (hello.i)
933
e x t e r n v o i d f u n l o c k f i l e ( FILE s t r e a m )
# 850 / u s r / i n c l u d e / s t d i o . h 3 4
attribute
((
nothrow
935
# 7 h e l lo . c 2
937
939
941
i n t main ( v o i d )
{
p r i n t f ( H e l l o , w o r l d ! \ n ) ;
return 0;
}
Listagem 1.3: C
odigo fonte pre-processado II (hello.i)
));
1.3.2. O compilador
O passo seguinte e a compilacao propriamente dita, do c
odigo pre-processado para linguagem
assembly adequada ao processador especfico da maquina onde a compilacao est
a a ser efectuada.
A opcao -S ordena ao gcc que converta o c
odigo pre-processado em linguagem assembly , sem que
seja criado nenhum ficheiro de objectos:
$ gcc -Wall -S hello.i
(1.10)
. LC0 :
4
10
12
14
16
18
20
22
24
26
. s t r i n g Hello , world !
. text
. g l o b l main
. type
main , @ f u n c t i o n
main :
leal
4(% e s p ) , %e c x
andl
$ 16 , %e s p
pushl
4(%e c x )
pushl
%ebp
movl
%esp , %ebp
pushl
%e c x
subl
$4 , %e s p
movl
$ . LC0 , (% e s p )
call
puts
movl
$0 , %e a x
addl
$4 , %e s p
popl
%e c x
popl
%ebp
leal
4(%e c x ) , %e s p
ret
. size
main , . main
. i d e n t GCC : (GNU) 4 . 1 . 0 20060304 ( Red Hat 4 . 1 . 0 3 )
. section
. n o t e . GNUs t a c k , , @ p r o g b i t s
Listagem 1.4: C
odigo fonte em assembly (hello.s)
1. O modelo de compilacao do C
1.3.3. O assembler
O objectivo do assembler e converter linguagem assembly em c
odigo de maquina e gerar um ficheiro
de objectos. Havendo chamadas a funcoes externas no c
odigo assembly , o assembler deixa os
enderecos dessas funcoes indefinidos, para serem depois completados pelo linker. O assembler
pode ser invocado atraves da seguinte linha de comandos:
$ as hello.s -o hello.o
(1.11)
, ou, alternativamente,
$ gcc -c hello.c
(1.12)
, ou, ainda,
$ gcc -c hello.s
(1.13)
(1.14)
00000000 T main
U puts
Como era de esperar, existem apenas duas funcoes: o main do nosso c
odigo em hello.c, e o printf,
aqui representado por puts. A parte importante e que, enquanto que ao main est
a associado um
endereco (o n
umero 00000000 na primeira coluna), ao puts n
ao, e por isso, aparece a letra U
(undefined symbol) na coluna central relativa a este objecto. Portanto est
a tudo pronto, falta
s
o colar os objectos, que e como quem diz, procurar onde est
ao os objectos que foram deixados
indefinidos pelo assembler de modo a que, quando o programa for executado, o sistema operativo
saiba o que fazer para executar todas as tarefas pedidas no c
odigo.
1.3.4. O linker
Chegamos ent
ao ao est
adio final da compilacao: o linker. Este ir
a linkar os ficheiros de objectos
e os objectos criando o execut
avel final. Na pratica, um execut
avel requer bastantes mais funcoes
associadas `
a interface com o sistema operativo durante o tempo de execucao (as chamadas run
time libraries). Consequentemente, as instrucoes de linkagem usadas internamente pelo gcc s
ao
em geral bastante complicadas. Por exemplo, o comando completo para linkar o programa Hello
World usando o GNU linker ld e
(1.15)
Dada a extensao .o do ficheiro hello.o, o gcc sabe que se trata de um ficheiro de objectos e, como
e o u
nico ficheiro passado, ele encarrega-se de linkar os seus objectos com a biblioteca standard do
C e gerar o execut
avel. Temos finalmente um programa utilizavel:
$ ./hello
Hello, world!
(1.16)
(1.17)
Este execut
avel em nada se distingue daquele que obtivemos mais acima de forma bastante menos
penosa atraves de uma invocacao u
nica do gcc em (1.5).
Para terminar podemos mesmo confirmar que o nosso execut
avel incorpora um conjunto muito
maior de objectos alem dos que definimos no nosso c
odigo fonte (o main e o printf), examinando
a tabela de smbolos do execut
avel. Para tal recorremos novamente ao comando nm:
$ nm hello
08049544 A
080482d0 t
08049544 b
08049444 d
08049440 d
08049538 D
08049538 W
080483e4 t
080482f8 t
0804953c D
0804944c d
08049448 d
08049454 d
08049544 A
0804843c r
08049548 A
08048408 T
08049440 a
08049440 a
08048424 R
__bss_start
call_gmon_start
completed.1
__CTOR_END__
__CTOR_LIST__
__data_start
data_start
__do_global_ctors_aux
__do_global_dtors_aux
__dso_handle
__DTOR_END__
__DTOR_LIST__
_DYNAMIC
_edata
__EH_FRAME_BEGIN__
_end
_fini
__fini_array_end
__fini_array_start
_fp_hw
08048334 t frame_dummy
0804843c r __FRAME_END__
08049520 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
08048254 T _init
08049440 a __init_array_end
08049440 a __init_array_start
08048428 R _IO_stdin_used
08049450 d __JCR_END__
08049450 d __JCR_LIST__
w _Jv_RegisterClasses
08048388 T __libc_csu_fini
08048390 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804835c T main
08049540 d p.0
08049440 a __preinit_array_end
08049440 a __preinit_array_start
U puts@@GLIBC_2.0
080482ac T _start
1. O modelo de compilacao do C
designadas de partilhadas.
10
$ ldd hello
linux-gate.so.1 => (0x002e2000)
libc.so.6 => /lib/libc.so.6 (0x00300000)
/lib/ld-linux.so.2 (0x002e3000)
Mas... isto significa que o execut
avel hello n
ao e independente! Ele s
o correra num sistema
onde existam estas 3 bibliotecas. Bom, neste caso isso n
ao e t
ao grave como parece porque, em
geral, qualquer sistema GNU /Linux ter
a um sistema de C e, sendo o mesmo tipo de arquitectura, o
nosso execut
avel correr
a l
a em princpio. Mas quando as dependencias partilhadas s
ao bibliotecas
ao disponveis no sistema onde pretendemos correr
especficas8, e importante garantir que elas estar
o programa com linkagem din
amica9 .
H
a casos em que poderemos n
ao estar muito interessados em que o nosso programa final fique
em geral possvel
com linkagem din
amica. Para esses casos h
a, felizmente, uma solucao simples. E,
especificar ao gcc que o execut
avel deve ser linkado estaticamente, mesmo quando os objectos
externos se encontram em bibliotecas partilhadas. O que acontece e que, quando nada e dito, o
gcc procede `
a linkagem din
amica daqueles objectos que se encontram em bibliotecas partilhadas
(porque em geral, como vimos, e o modo mais eficiente de usar os recursos em memoria e disco).
Mas, se os objectos se encontram l
a arquivados nessas bibliotecas, deve ser possvel usa-los como
qualquer outros ficheiros .o e, em particular, link
a-los estaticamente. Isso consegue-se passando a
opcao --static ao gcc . Portanto, se eu quiser criar um execut
avel do Hello World com linkagem
est
atica basta fazer:
$ gcc -Wall hello.c --static -o hello-static
(1.18)
(1.19)
(1.20)
(1.21)
Ca est
a: n
ao tem dependencias din
amicas nenhumas. Mas, claro, existem sempre os tais sen
ao a
que aludimos acima. Como o hello-static est
a agora linkado estaticamente, todos os objectos
fazem parte do execut
avel, incluindo os das run time libraries. Ora vejamos. Para hello, que e
dinamico, tenho no meu sistema:
$ nm hello | wc -l
39
(1.22)
(1.23)
8 Como
9 Eis
11
1. O modelo de compilacao do C
(1.24)
(1.25)
nada mais nada menos do que 1787 objectos! Isto reflecte-se, obviamente, no tamanho do executavel: enquanto que o execut
avel hello ocupa
$ ls -lh hello
-rwxr-xr-x 1 vpereira users 4.6K May 24 10:57 hello
(1.26)
(1.27)
12
(1.28)
(1.29)
2. Compilac
ao de m
ultiplas files
2.1. Distribuic
ao de c
odigo
Depois de alguma pratica ou necessidade de programacao, facilmente se chega a um ponto em
que se torna conveniente dividir o c
odigo de um programa por varios ficheiros separados. Entre
muitas outras vantagens, esta divisao torna o c
odigo muito mais facil de gerir e, sobretudo se se
trata de c
odigo extenso e complexo, de entender. Entre as maiores vantagens de assim proceder,
est
a a possibilidade de compilar as diversas partes desse programa separada e independentemente.
Os programadores, em geral, desenham um programa dividindo-o por seccoes representativas de
determinadas tarefas que se pretende desempanhar. A ideia e que cada uma destas seccoes esteja
contida num ou mais ficheiros, os quais poder
ao conter uma ou varias funcoes. Um dos ficheiros
conter
a necessariamente o main(), e os restantes poder
ao ser considerados como uma biblioteca
de funcoes.
Para perceber como tal e possvel e como se efectua na pratica, nada melhor do que um exemplo
simples, nesta altura j
a nosso conhecido. No exemplo seguinte, dividiremos o programa Hello
a o nosso header file
World por tres ficheiros separados: main.c, hello fn.c e hello.h que ser
particular. Eis no que consiste o c
odigo de main.c:
/
F i l e main . c
U t i l i z a d a p a r a d e m o n s t r a r a d i s t r i b u i c a o de c o d i g o
por d i v e r s a s f i l e s .
V i t o r M. P e r e i r a
/
#i n c l u d e h e l l o . h
10
12
14
i n t main ( v o i d )
{
h e l l o ( world ) ;
return 0;
}
13
2. Compilacao de m
ultiplas files
10
/
File hello fn . c
U t i l i z a d a p a r a d e m o n s t r a r a d i s t r i b u i c a o de c o d i g o
p o r d i v e r s a s f i l e s . Contem a d e f i n i c a o da f u n c a o
h e l l o u s a d a p e l o main . c
V i t o r M. P e r e i r a
/
#i n c l u d e < s t d i o . h>
#i n c l u d e h e l l o . h
12
14
16
void
h e l l o ( c o n s t c h a r name )
{
p r i n t f ( H e l l o , %s ! \ n , name ) ;
}
Listagem 2.2: C
odigo fonte do segmento hello fn.c.
Ou seja, esta funcao apenas imprime a string passada como argumento para o stdout, em geral,
o terminal. Claro que, como sabemos, o compilador precisa de conhecer as declaracoes de todas
as funcoes antes que estas sejam chamadas pela primeira vez. Da que, como a funcao hello ser
a
definida fora de main.c, seja necess
ario incluir um prot
otipo seu para que o seu tipo, argumentos
e return value sejam conhecidos pelo compilador quando este processar o ficheiro main.c. Isso
est
a assegurdo pela instrucao #include "hello.h" passada no cabecalho de main.c1. No nosso
header poremos apenas o tal prot
otipo:
/
File hello2 . h
U t i l i z a d a p a r a d e m o n s t r a r a d i s t r i b u i c a o de c o d i g o
p o r d i v e r s a s f i l e s . S e r a o h e a d e r comum que contem o
p r o t o t i p o da f u n c a o h e l l o r e q u e r i d a p e l o main . c
/
v o i d h e l l o ( c o n s t c h a r name ) ;
v o i d bye ( v o i d ) ;
Portanto, n
ao obstante estar repartido por tres ficheiros, este programa faz exactamente o mesmo
que o c
odigo apresentado na Listagem 1.1. Para o compilar, um dos metodos consiste em passar
importante que saiba a diferenca e o
que foi usado #include "hello.h" e n
ao #include <hello.h>. E
significado de cada uma das formas.
1 Note-se
14
2.1. Distribuicao de c
odigo
todos os ficheiros do c
odigo fonte ao gcc :
$ gcc -Wall main.c hello fn.c -o newhello
(2.1)
(2.2)
(2.3)
que
e precisamente o linker (o j
a nosso conhecido ld) quem se queixa atrav
es da mensagem collect2:
ld returned 1 exit status
3 Al
em do que, como
e evidente, fica muito mais f
acil trabalhar com v
arios ficheiros pequenos, do que com um
mega-ficheiro onde, apesar de toda a dilig
encia dos editores de texto, se poder
a perder mais tempo a
` procura da
linha a corrigir, do que a efectuar ou pensar na correcca
o.
15
2. Compilacao de m
ultiplas files
(2.4)
ir
a compilar o c
odigo em main.c e, em vez de gerar um execut
avel gera apenas um novo ficheiro
de objectos main.o. O comando correspondente para o ficheiro que contem a definicao da funcao
e
$ gcc -Wall -c hello fn.c
(2.5)
Nestes casos, n
ao e necess
ario usar a opcao -o para instruir o compilador `acerca do nome para o
ficheiro de objectos resultante, j
a que o gcc cria automaticamente um ficheiro com o mesmo nome,
substituindo .c por .o4 .
(2.6)
(2.7)
(2.8)
e evidente, a opca
o -o pode ser usada tamb
em aqui, no caso de querermos que o ficheiro de objectos tenha
um nome diferente. No entanto isso raramente se justifica.
5 O link falha sempre que existam objectos que o linker n
ao consegue identificar ou encontrar. E se isso acontece o
execut
avel n
ao pode ser criado: n
ao faz sentido dar ao linker o livre arbtrio de decidir continuar neste ou naquele
caso (como o compilador, no sentido estrito, faz) porque perderamos totalmente o controlo e deixaramos de
estar a fazer programaca
o.
16
/
F i l e main . c
U t i l i z a d a p a r a d e m o n s t r a r a d i s t r i b u i c a o de c o d i g o
por d i v e r s a s f i l e s .
V i t o r M. P e r e i r a
/
#i n c l u d e h e l l o . h
10
12
14
i n t main ( v o i d )
{
h e l l o ( everyone ) ;
return 0;
}
(2.9)
Dado que nada mudou no que diz respeito aos restantes segmentos do c
odigo, n
ao h
a necessidade
nica coisa a fazer e re-linkar o main.o com os
de recompilar a outro ficheiro hello fn.c. A u
ficheiros de objectos j
a compilados anteriormente:
$ gcc main.o hello fn.o -o newhello
(2.10)
(2.11)
(2.12)
Para um projecto computacional extenso, este modo de proceder poupa valioso tempo ao programador entre compilacoes. Estes passos podem ser facilmente automatizados atraves de um script
que incorpore a sequencia de comandos acima. Tudo isso, incluindo a verificacao autom
atica dos
ficheiros que carecem de recompilacao, e feito de um modo muito eficiente pelo programa make que
abordaremos mais adiante.
importante que n
E
ao se fique com a ideia de que utilidade deste esquema de compilacao se
limita aos casos de grandesprogramas, e aplicacoes complexas. Um exemplo t
ao prosaico como
a um exemplo desta metodologia em funcionamento: (quase)
um programa que calcule 2 e j
ninguem ir
a definir a sua propria funcao sqrt() para obter tal resultado. Ir
a, isso sim, recorrer,
por exemplo ao sqrt() fornecido pela biblioteca matematica do C . Mas ninguem ir
a compilar a
totalidade da biblioteca standard do C sempre que quiser calcular uma raz quadrada! Toda a gente
sabe que basta simplesmente utiliz
a-la compilando o c
odigo com a opcao -lm. Esta utilizaca
o
17
2. Compilacao de m
ultiplas files
t
ao trivial s
o e possvel porque sqrt(), juntamente com todos os outros objectos que constituem
essa biblioteca, existem j
a no sistema pre-compilados. O programador apenas trata de os linkar (o
-lm faz isso mesmo) com o seu c
odigo, de forma completamente transparente e c
omoda.
Numa u
ltima nota, igualmente evidente, diremos que a modularizacao de um programa permite
que uma determinada funcao, ou conjunto de funcoes, possa ser utilizado por varios programas
diferentes, sem que haja a necessidade de reescrever ou copiar constantemente o seu c
odigo de
programa para programa. Isto e u
til em todas as circunst
ancias, aplicando-se nomeadamente `as
rotinas numericas desenvolvidas no
ambito da cadeira de Fsica Computacional.
2.5.1. Ambito
(Scope)
Qualquer vari
avel presente no c
odigo fonte tem um ambito6 . O ambito da vari
avel define a porcao
do programa onde essa vari
avel est
a acessvel, pode ser acedida e manipulada. Para uma analogia, imagine-se um transeunte na rua. A partir do seu posto, ele pode ver determinadas coisas,
como sejam os predios `
a sua volta, ou outras pessoas na rua. Mas h
a certas coisas que ele n
ao
consegue ver, como sejam as pessoas que est
ao dentro dos predios que ele ve. Mas estas u
ltimas
conseguirao ver o transeunte das suas janelas. Precisamente do mesmo modo, algumas vari
aveis
de um programa s
ao como este homem visveis a partir de qualquer outra parte do programa
(as vari
aveis globais), enquanto que outras se encontram escondidas como os moradores dentro
das paredes que s
ao os parentesis curvos {}.
Os principais
ambitos possveis s
ao:
Prot
otipo Vari
aveis/funcoes numa lista de par
ametros de um prot
otipo de funcao tem ambito de
prot
otipo. Como se trata de um ambito altamente limitado, estes identificadores s
ao, na
pratica, pouco mais do que coment
arios.
6 N
ao
18
apenas as vari
aveis, mas qualquer identificador, tem um a
mbito.
Bloco Vari
aveis/funcoes declaradas dentro de um bloco ({}) tem o ambito desse bloco. Os
par
ametros de uma funcao, em particular, tem ambito de bloco sendo este delimitado pelos
({}) que delimitam a sua definicao. O ambito inicia no ponto em que a vari
avel e declarada,
e termina com o } do bloco correspondente.
File Vari
aveis/funcoes declaradas fora de todos os blocos e listas de par
ametros tem ambito de
ficheiro. O
ambito de ficheiro principia no ponto da declaracao extendendo-se ate ao final
desse ficheiro de c
odigo.
A listagem seguinte exemplifica alguns casos:
/
F i l e scope . c
Exemplos de s c o p e / a m b i t o de v a r i a v e i s
V i t o r M. P e r e i r a
/
int a ;
10
12
14
i n t main ( )
{
int b ;
16
// Ambito g l o b a l . A v a r i a v e l a e v i s i v e l n e s t e p o n t o do
// programa , e a t e ao f i n a l d e s t e f i c h e i r o de c o d i g o mas
// a s v a r i a v e i s b e c nao s a o v i s i v e i s a q u i .
//
//
//
//
Ambito l o c a l no main ( ) . As v a r i a v e i s a e b s a o
v i s i v e i s a q u i . A v a r i a v e l b e v i s i v e l a t e ao } que
t e r m i n a o main ( ) . V a r i a v e i s c e d nao s a o v i s i v e i s
aqui .
18
{
int c ;
20
22
24
int d ;
26
// Ambito l o c a l n e s t e b l o c o d e l i m i t a d o p o r e s t e s
// { . . . } . V a r i a v e i s a , b e c s a o t o d a s v i s i v e i s a q u i .
//
//
//
//
Ambito l o c a l no main ( ) . As v a r i a v e i s a e b e d s a o
v i s i v e i s a q u i . A v a r i a v e l d tem um s c o p e a n a l o g o ao
de b , mas m a i s l i m i t a d o , uma v e z que e s s e s c o p e
comeca n e s t e p o n t o e a t e ao f i m do main ( ) .
return 0;
28
19
2. Compilacao de m
ultiplas files
o da Declarac
o
Posic
a
a
Especificador
Ambito
o
Durac
a
File
Bloco
Bloco
Est
atica
Autom
atica
Est
atica
20
2.6. Organizac
ao dos dados em cada ficheiro
Todos os ficheiros de c
odigo devem ter uma organizacao coerente e funcional. A ordem pela qual
as instrucoes aparecem num ficheiro de c
odigo e, tipicamente:
Um pre
ambulo, onde constar
ao varios #define, #include, e typedef relativos a tipos de
dados importantes;
Declaracao de todas as vari
aveis externas e globais. Estas u
ltimas poder
ao ser inicializadas
tambem nesta fase;
Uma ou varias funcoes.
A ordem destes items e importante, uma vez que em C todo e qualquer objecto tem de ser declarado
antes de utilizado pela primeira vez. Funcoes com return, devem ser definidas, ou pelo menos
prototipadas, antes de serem chamadas. Estes prot
otipos encontram-se geralmente numa das
header file (*.h).
21
2. Compilacao de m
ultiplas files
22
3. Criac
ao de Bibliotecas
Um biblioteca e uma coleccao de ficheiros de objectos reunidos num u
nico ficheiro designado de
portanto, um modo conveniente de distribuir um largo n
arquivo. E,
umero de ficheiros de objectos
relacionados entre si. Para exemplicar esta funcionalidade, e como se pode tirar partido dela,
demonstraremos a seguir como usar a aplicacao ar (GNU archiver) para criar um biblioteca est
atica1 .
Invoquemos o nosso sempre presente projecto do Hello World, para o qual vamos criar uma
biblioteca chamada libhello.a que vai conter a definicao de duas funcoes. Uma delas e a funcao
aa
hello() que est
a definida no ficheiro hello fn.c apresentado na Listagem 2.2. A outra ser
funcao bye() que definiremos num ficheiro chamado bye fn.c:
/
F ile bye fn . c
U t i l i z a d a p a r a d e m o n s t r a r a d i s t r i b u i c a o de c o d i g o
p o r d i v e r s a s f i l e s . Contem a d e f i n i c a o da f u n c a o
bye u s a d a p e l o main . c
V i t o r M. P e r e i r a
/
11
#i n c l u d e < s t d i o . h>
#i n c l u d e h e l l o 2 . h
13
15
17
v o i d bye ( v o i d )
{
p r i n t f ( Goodbye ! \ n ) ;
}
/
File hello2 . h
U t i l i z a d a p a r a d e m o n s t r a r a d i s t r i b u i c a o de c o d i g o
p o r d i v e r s a s f i l e s . S e r a o h e a d e r comum que contem o
p r o t o t i p o da f u n c a o h e l l o r e q u e r i d a p e l o main . c
/
1 Limitamo-nos
aqui a
` descrica
o de bibliotecas est
aticas
23
3. Criacao de Bibliotecas
v o i d h e l l o ( c o n s t c h a r name ) ;
v o i d bye ( v o i d ) ;
hello_fn.o
(3.1)
O cr acima trata-se de duas opcoes para o ar (c: criar o arquivo, r: substituir no caso de ja
existir um .o com o mesmo nome no arquivo). O nome pretendido para a biblioteca (libhello.a)
e passado antes dos seus membros e, se ela ainda n
ao existir ser
a ent
ao criada. O ar tambem
permite listar o conte
udo das bibliotecas, atraves da opcao t (tabelar):
$ ar t libhello.a
hello_fn.o
bye_fn.o
Bom, agora que temos uma biblioteca h
a que lhe dar algum uso. Para isso criamos um main
bem simples:
/
F i l e main . c
U t i l i z a d a p a r a d e m o n s t r a r a u t i l i z a c a o de
uma b i b l i o t e c a recemc r i a d a .
V i t o r M. P e r e i r a
/
#i n c l u d e h e l l o 2 . h
10
12
14
16
i n t main ( v o i d )
{
h e l l o ( everyone ) ;
bye ( ) ;
return 0;
}
24
(3.2)
, que fara com que o main() seja linkado com os objectos da biblioteca. A segunda hipotese e usar
um atalho e recorrer `
a opcao -l do gcc :
$ gcc -Wall -L. main3.c -lhello -o hello
(3.3)
Neste u
ltimo comando, a opcao -lhello instrui o gcc a linkar com a biblioteca libhello.a, e -L
serve para dizer ao gcc para procurar essa biblioteca na directoria actual2 . Note-se que a nossa
recem-criada biblioteca libhello.a e passada ao gcc como passaramos, por exemplo, a biblioteca
matematica usando -lm. A parte a reter e que, quando uma bibliteca e passada ao gcc atraves do
-l, deve indicar-se apenas a porcao no seu nome que vem `a frente de lib, tal como fizemos acima.
Correndo o nosso execut
avel obtemos ent
ao:
$ ./hello
Hello, everyone!
Goodbye!
, e confirmamos a simplicidade que e criar e usar uma biblioteca definida `a medida das nossas
necessidades. Fica implcito no que se referiu acima que esta nossa biblioteca e usada e invocada
como qualquer outra biblioteca est
atica do sistema ou standart do C (n
ao tem um estatuto superior
nem inferior por ter sido criada por n
os).
2E
25
3. Criacao de Bibliotecas
26
4. Criac
ao e gest
ao de uma Makefile
Para aqueles n
ao familiarizados com o programa make , este captulo apresenta uma demonstracao
simples da sua utilizacao. O make entra em cena sempre que o nosso c
odigo comeca a ficar dema quase impens
siado extenso e/ou segmentado em diferentes ficheiros e bibliotecas. E
avel compilar
um programa com dezenas de ficheiros de c
odigo, usando uma instrucao gcc para cada um deles numa shell. Alem disso, j
a sabemos que em muitos casos, apenas um ficheiro precisa de ser
recompilado, mesmo em projectos grandes.
O make determina automaticamente quais s
ao as partes do programa que carecem de recompilacao e procede `
a compilacao apenas destes segmentos. Para isso, o make usa um script, um
conjunto de regras e instrucoes, criado pelo programador e normalmente chamado Makefile . A
Makefile contem basicamente um resumo do projecto, das dependencias e das instrucoes de compilacao para gerar um ou varios produtos finais.
Mais concrectamente, a Makefile especifica um conjunto de regras de compilacao em termos
de alvos (targets) como sejam os execut
aveis finais pretendidos e das suas dependencias
como sejam as fontes ou ficheiros de objectos de acordo com o formato seguinte:
alvo:
depend^
encias
comando
Para cada alvo, o make verifica o tempo da u
ltima alteracao de todas as suas dependencias para
deteminar quais delas foram alteradas e, consequentemente, necessitam de ser recompiladas usando
muito importante reter que as linhas onde se encontra(m) o(s) comando devem ser
o comando. E
indentadas com um u
nico TAB, sem espacos.
O make da GNU contem um conjunto implcito de regras que simplificam muito a construcao de
Makefile s. Estas especificam, por exemplo, que ficheiros .o s
ao obtidos de ficheiros .c atraves
de compilacao; e que um execut
avel se cria linkando os ficheiros .o. Estas regras implcitas est
ao
definidas em termos de vari
aveis, tais como CC (o compilador de C ), ou CFLAGS (as opcoes de
compilacao a passar ao compilador). Estas e quaisquer outras vari
aveis podem ser definidas usando
instrucoes do tipo
VARIAVEL=VALOR
em qualquer ponto da Makefile . Vejamos um exemplo do make em accao retomando o nosso
exemplo do programa Hello World repartido em ficheiros separados, tal como discutido na seccao
2. Antes de mais nada criamos a Makefile seguinte usando um editor de texto convencional:
27
# F i l e Makefile
# Exemplo de uma m a k e f i l e p a r a o H e l l o World
# D e f i n a m o s que o n o s s o c o m p i l a d o r e o g c c :
CC=g c c
10
# D e f i n a m o s q u a i s a s o p c o e s a p a s s a r ao g c c
CFLAGS=W a l l
# Definamos o t a r g e t para c o m p i l a r e g e r a r o e x e c u t a v e l
main : main . o h e l l o f n . o
12
14
28
29
30
Parte II.
31
Resumo
Nesta parte descreve-se o modo como rotinas escritas em FORTRAN podem ser usadas por
programadores em C . O objectivo e facilitar a utilizacao de rotinas existentes, ja que as
bibliotecas cientficas s
ao quase todas escritas em FORTRAN . Os exemplos apresentados
usam rotinas da cml (Common mathematical library) do SLATEC (Sandia, Los Alamos,
Air Force Weapons Laboratory, Tecnhical Expert Committee). Os compiladores em
que os exemplos foram testados s
ao os compiladores da GNU , gcc e g77, a correr em
maquinas linux. O material deste artigo e baseado no site de Bertrand Laubsh da
Universidade do Oregon.
4.1.1. Convenc
ao de nomes
A maior parte dos compiladores de FORTRAN, junta um undescore , , aos nomes das funcoes
ou subrotinas. Os compiladores de C, em geral, n
ao. Assim acontece com os compiladores gcc e
g77. Uma rotina com o nome
TWICE
em FORTRAN ser
a referida num programa em C como
twice
33
A= 2*A
a vari
avel A ter
a o seu valor alterado no programa de chamada. Isto significa que no programa
em C a funcao twice deve ter como argumento um apontador (pointer) para a vari
avel A. A
declaracao de twice seria ent
ao
double twice (double *);
e um fragmento de c
odigo possvel seria:
double twice (double *);
double b;
double a=3.0;
b = twice (&a);
11
C F i l e :
twice . f
C F u n c t i o n to be c a l l e d by a C program
C
DOUBLE PRECISION FUNCTION TWICE(X)
C Comment
C Return 2 argument
DOUBLE PRECISION X , Y
Y=2.0
TWICE=YX
RETURN
END
C THE END
11
13
/
file :
c a l l t w i c e . c T h i s program c a l l s t w i c e ( x )
Notes :
g c c n e e d s t h e u n d e r s c o r e appended t o f u n c i o n names .
F o r t r a n ALWAYS P a s s e s r e f e r e n c e s , n o t v a l u e s . So a r g u m e n t s i n f u n c
t i o n c a l l h a v e t o be p o i n t e r s .
V i t o r M. P e r e i r a
/
#i n c l u d e <math . h>
double t w i c e ( double ) ;
34
15
/ argument must be p o i n t e r /
23
i n t main ( ) {
double x , y ;
x =2.0;
y=t w i c e (&x ) ;
p r i n t f ( Two t i m e s two i s %g . \ n , y ) ;
return 0;
}
25
/ end o f c a l l t w i c e /
17
19
21
Listagem 4.3: Exemplo de um programa em C que chama uma rotina de FORTRAN (calltwice.c).
4.1.3. Compilac
ao
O problema essencial da compilacao e a inclus
ao correcta das bibliotecas usadas pelos programas.
No caso acima indicado h
a duas possibilidades:
Compilar files nomef .f com g77 e compilar e linkar os ficheiros nomec .c com nomef .o e
a biblioteca matematica do C com gcc;
Compilar files nomec .c com gcc e compilar e linkar os ficheiros nomef .f com nomec .o
com o g77.
No caso da seccao anterior qualquer dos seguintes procedimentos funciona:
$ gcc -c calltwice.c
$ g77 calltwice.o twice.f
Ou,
$ g77 twice.f
$ gcc twice.o calltwice.c -lm
35
As rotinas de integracao numerica disponveis nas bibliotecas numericas usam, quase sempre,
metodos de quadratura gaussiana. Estes metodos s
ao baseados numa aproximacao do tipo
Z
dxw(x)f (x)
f (xk )wk
10
12
14
16
18
20
22
24
DECK DGAUS8
SUBROUTINE DGAUS8 (FUN , A , B , ERR, ANS , IERR )
C BEGIN PROLOGUE DGAUS8
CPURPOSE I n t e g r a t e a r e a l f u n c t i o n o f one v a r i a b l e o v e r a f i n i t e
C
i n t e r v a l u s i n g an a d a p t i v e 8 p o i n t L e g e n d r e Gauss
C
algorithm .
Intended p r i m a r i l y f o r high accuracy
C
i n t e g r a t i o n o r i n t e g r a t i o n o f smooth f u n c t i o n s .
C LIBRARY
SLATEC
CCATEGORY H2A1A1
CTYPE
DOUBLE PRECISION (GAUS8S , DGAUS8D)
CKEYWORDS ADAPTIVE QUADRATURE, AUTOMATIC INTEGRATOR ,
C
GAUSS QUADRATURE, NUMERICAL INTEGRATION
CAUTHOR Jones , R . E . , (SNLA)
C DESCRIPTION
C
C
A b s t r a c t a DOUBLE PRECISION r o u t i n e
C
DGAUS8 i n t e g r a t e s r e a l f u n c t i o n s o f one v a r i a b l e o v e r f i n i t e
C
i n t e r v a l s u s i n g an a d a p t i v e 8 p o i n t L e g e n d r e Gauss a l g o r i t h m .
C
DGAUS8 i s i n t e n d e d p r i m a r i l y f o r h i g h a c c u r a c y i n t e g r a t i o n
C
o r i n t e g r a t i o n o f smooth f u n c t i o n s .
C
C
The maximum number o f s i g n i f i c a n t d i g i t s o b t a i n a b l e i n ANS
C
i s t h e s m a l l e r o f 18 and t h e number o f d i g i t s c a r r i e d i n
C
double p r e c i s i o n a r i t h m e t i c .
C
36
26
28
30
32
34
36
38
40
42
44
46
48
50
52
54
56
58
60
62
64
66
68
70
72
74
76
78
C
D e s c r i p t i o n o f Arguments
C
C
I n p u t FUN , A , B , ERR a r e DOUBLE PRECISION
C
FUN name o f e x t e r n a l f u n c t i o n to be i n t e g r a t e d .
T h i s name
C
must be i n an EXTERNAL s t a t e m e n t i n t h e c a l l i n g program .
C
FUN must be a DOUBLE PRECISION f u n c t i o n o f one DOUBLE
C
PRECISION argument . The v a l u e o f t h e argument to FUN
C
i s t h e v a r i a b l e o f i n t e g r a t i o n w h i c h r a n g e s from A to B .
C
A
lower l i m i t of i n t e g r a t i o n
C
B
u p p e r l i m i t o f i n t e g r a t i o n ( may be l e s s t h a n A)
C
ERR i s a r e q u e s t e d p s e u d o r e l a t i v e e r r o r t o l e r a n c e .
Normally
C
p i c k a v a l u e o f ABS(ERR) s o t h a t DTOL . LT . ABS(ERR) . LE .
C
1 . 0 D3 where DTOL i s t h e l a r g e r o f 1 . 0 D18 and t h e
C
double p r e c i s i o n u n i t r o u n d o f f D1MACH ( 4 ) . ANS w i l l
C
n o r m a l l y h a v e no more e r r o r t h a n ABS(ERR) t i m e s t h e
C
i n t e g r a l o f t h e a b s o l u t e v a l u e o f FUN(X ) .
Usually ,
C
s m a l l e r v a l u e s o f ERR y i e l d more a c c u r a c y and r e q u i r e
C
more f u n c t i o n e v a l u a t i o n s .
C
C
A n e g a t i v e v a l u e f o r ERR c a u s e s an e s t i m a t e o f t h e
C
a b s o l u t e e r r o r i n ANS to be r e t u r n e d i n ERR . Note t h a t
C
ERR must be a v a r i a b l e ( n o t a c o n s t a n t ) i n t h i s c a s e .
C
Note a l s o t h a t t h e u s e r must r e s e t t h e v a l u e o f ERR
C
b e f o r e making any more c a l l s t h a t us e t h e v a r i a b l e ERR .
C
C
Output ERR, ANS a r e double p r e c i s i o n
C
ERR w i l l be an e s t i m a t e o f t h e a b s o l u t e e r r o r i n ANS i f t h e
C
i n p u t v a l u e o f ERR was n e g a t i v e .
(ERR i s unchanged i f
C
t h e i n p u t v a l u e o f ERR was nonn e g a t i v e . ) The e s t i m a t e d
C
e r r o r i s s o l e l y f o r i n f o r m a t i o n to t h e u s e r and s h o u l d
C
n o t be u s e d a s a c o r r e c t i o n to t h e computed i n t e g r a l .
C
ANS computed v a l u e o f i n t e g r a l
C
IERR a s t a t u s c o d e
C
Normal c o d e s
C
1 ANS most l i k e l y meets r e q u e s t e d e r r o r t o l e r a n c e ,
C
o r A=B .
C
1 A and B a r e t o o n e a r l y e q u a l to a l l o w n o r m a l
C
i n t e g r a t i o n . ANS i s s e t to z e r o .
C
Abnormal c o d e
C
2 ANS p r o b a b l y d o e s n o t meet r e q u e s t e d e r r o r t o l e r a n c e .
C
CREFERENCES (NONE)
CROUTINES CALLED D1MACH, I1MACH , XERMSG
C REVISION HISTORY (YYMMDD)
C
810223 DATE WRITTEN
C
890531 Changed a l l s p e c i f i c i n t r i n s i c s to g e n e r i c .
(WRB)
C
890911 Removed u n n e c e s s a r y i n t r i n s i c s .
(WRB)
C
890911 REVISION DATE from V e r s i o n 3 . 2
C
891214 P r o l o g u e c o n v e r t e d to V e r s i o n 4 . 0 format .
(BAB)
C
900315 CALLs to XERROR changed to CALLs to XERMSG .
(THJ)
C
900326 Removed d u p l i c a t e i n f o r m a t i o n from DESCRIPTION s e c t i o n .
C
(WRB)
CEND PROLOGUE DGAUS8
37
Listagem 4.4: Pr
ologo da rotina DGAUS8 do SLATEC (dgaus8.f).
Se o pacote slatec4linux.tgz (ver apendice 6) estiver correctamente instalado, este prologo pode
ser visto usando o comando man do unix, man dgaus8. A biblioteca SLATEC tem em qpdoc uma
introducao a varias rotinas de integracao. Para a ver basta executar o comando man qpdoc.
Olhemos agora para um programa em C que chama esta rotina:
/
Example o f c a l l o f a s l a t e c r o u t i n e t h a t
t a k e s a f u n c t i o n name a s argument
J .M. B . L o p e s d o s S a n t o s
F i s i c a C o m p u t a c i o n a l Maio 2001
/
#i n c l u d e < s t d i o . h>
#i n c l u d e <math . h>
10
14
t y p e d e f double d d f o r t r a n ( double ) ; / d d f o r t r a n d e c l a r e s a f u n c t i o n
r e tur ni ng double
taking a p oin t er to double
a s argument /
16
/ Here i s t h e s l a t e c r o u t i n e .
18
12
20
22
24
26
28
30
32
main ( )
{
d d f o r t r a n pfunc ;
/ p f u n c i s a p o i n t e r t o a d d f o r t r a n f u n c t i o n /
double f u n c ( double ) ;
/ i n t e g r a n d
/
double a = 0 . 0 ;
/ i n t e g r a l l i m i t s /
double b = 1 . 0 ;
double e r r o =1.E7;
/ t o l e r a t e d e r r o r /
double i n t e g ;
/ t o s t o r e i n t e g r a l v a l u e /
int I e rr ;
/ f l a g f o r e r r o r c o n d i t i o n /
p f u n c =&f u n c ;
/ p f u n c p o i n t s t o f u n c /
d g a u s 8 ( p f u n c , &a , &b , &e r r o , &i n t e g , & I e r r ) ; / t h e
s l a t e c r o u t i n e /
p r i n t f ( %e \ t %e \n , i n t e g , e r r o ) ;
}
38
double f u n c ( double x )
{
double y = x ;
return yy ;
}
40
34
36
Check d g a u s 8 d o c u m e n t a t i o n /
/ t h e i n t e g r a n d /
End d g a u s 8 . c To c o m p i l e s i m p l y do :
g c c c
dgaus8 . c
42
38
g77 d g a u s 8 . o l s l a t e c l l a p a c k
44
Listagem 4.5: Exemplo de programa em C que chama a rotina DGAUS8 do SLATEC (calldgaus8.c).
A funcao dgaus8 tem como primeiro argumento o nome de uma funcao. Em C teremos que passar
um apontador para uma funcao. A declaracao
typedef double ddfortran(double *);
define um novo tipo, ddfortran, que corresponde a uma funcao de dupla precisao com argumento
que e um apontador para vari
avel double. A instrucao
ddfortran *pfunc;
pfunc fica a apontar para a funcao func. pfunc e o primeiro argumento de dgaus8. Os restantes
argumentos s
ao apontadores para diferentes vari
aveis, tal como foi descrito no exemplo anterior.
Para compilar este exemplo podemos compilar o programa em C
$ gcc -c dgaus8.c
e depois link
a-lo com a biblioteca SLATEC (que pode necessitar da LAPACK).
$ g77 dgaus8.o -lslatec -llapack
Eventualmente, podemos ter que indicar o PATH da biblioteca libslatec. Por exemplo, se estiver
instalada em /usr/local/lib
$ g77 dgaus8.o -L/usr/local/lib -lslatec -llapack
4.3. Documentac
ao da Biblioteca SLATEC
A instalacao da biblioteca SLATEC exige dois pacotes, slatec4linux.tgz e slatec src.tgz, ambos disponveis no site da netlib [1]. As instrucoes para instalacao est
ao no apendice 6. A documentacao fica instalada em man pages. O comando
39
4.4. Enderecos
uteis
[1] http://www.netlib.org Reposit
orio de software para c
alculo cientfico.
[2] http://gams.nist.gov indce cruzado e repositorio de software matematico e estatstico.
Excelente facilidades de procura. Estruturado com a classificacao gams (Guide to availbale
mathematical software).
[3] http://www.physics.orst.edu/bertrand/C slatec html/begin.html Um site com um
tutorial de utilizacao da biblioteca slatec a partir de C.
40
Parte III.
A Biblioteca gsl
por Eduardo Castro e Vitor M. Pereira (em Construc
ao)
41
5. T
opicos preliminares
5.1. O que
e a gsl
A GNU Scientific Library (gsl ) reune um conjunto de rotinas para c
alculo numerico a maior
parte delas bastante testadas ao longo de muitos anos que foram re-escritas de raz em C , e com
especial preocupacao na interface entre a biblioteca e o programa/programador, garantindo assim
a sua utilizacao n
ao s
o em ambiente C , mas em muitas outras linguagens de alto nvel (o Python,
por exemplo).
A biblioteca abrange um vasto n
umero de t
opicos em an
alise numerica, tendo disponveis rotinas
nas seguintes `
areas:
Complex Numbers
Roots of Polynomials
Special Functions
Vectors and Matrices
Permutations
Combinations
Sorting
BLAS Support
Linear Algebra
CBLAS Library
Fast Fourier Transforms
Eigensystems
Random Numbers
Quadrature
Random Distributions
Quasi-Random Sequences
Histograms
Statistics
Monte Carlo Integration
N-Tuples
Differential Equations
Simulated Annealing
Numerical Differentiation
Interpolation
Series Acceleration
Chebyshev Approximations
Root-Finding
Discrete Hankel Transforms
Least-Squares Fitting
Minimization
IEEE Floating-Point
Physical Constants
Wavelets
5.2. Utilizac
ao b
asica
Comecemos por um exemplo bastante simples. Uma das seccoes da gsl fornece verias ferramentas
relativas a funcoes especiais. Consideremos o c
odigo seguinte que calcula a funcao de Bessel J0 (x)
para x = 5:
/
F i l e g s l b e s s e l . c
D emonstracao de u t i l i z a c a o da g s l
43
5. Topicos preliminares
V i t o r M. P e r e i r a
/
#i n c l u d e < s t d i o . h>
#i n c l u d e < g s l / g s l s f b e s s e l . h>
10
12
14
16
i n t main
{
double
double
printf
return
}
( void )
x = 5.0;
y = gsl sf bessel J0 (x );
( J0(%g ) = %.18 e \n , x , y ) ;
0;
A instrucao #include <gsl/gsl sf bessel.h> trata de carregar o header da gsl onde as funcoes
de Bessel est
ao declaradas. Neste #include foi passado, n
ao s
o o nome do header, como tambem
uma parte do seu caminho. Isto acontece porque, no meu sistema, os headers da gsl encontram-se
todos no direct
orio /usr/include/gsl/ e, logo, como o gcc em princpio s
o procura headers em
/usr/include/, e necess
ario dar o resto do caminho.
A funcao gsl sf bessel J0() e uma das funcoes oferecidas pela gsl , e o seu prot
otipo e
simplesmente1
double gsl_sf_bessel_J0 (double X)
Para compilar este programa fazemos:
$ gcc -Wall gsl-bessel.c -lgsl -lgslcblas -o gsl-bessel
(5.1)
Esta instrucao compila o nosso programa gsl-bessel.c e procede `a linkagem com a gsl . Como
ja sabemos desde a seccao 3, a opcao -lgsl pede ao compilador que faca o link com uma biblioteca
chamada libgsl.a (ou libgsl.so). Numa instalacao convencional, ela estar
a em /usr/lib/.
Caso contr
ario, pode ser necess
ario acrescentar a opcao -Lcaminho com o caminho para onde esta
biblioteca estiver instalada. Mas vemos que existe outra biblioteca, chamada libgslblas.a, a ser
linkada com o nosso programa. Bom, na verdade n
ao e com o nosso programa mas sim com a gsl .
Ou seja, a libgsl.a depende desta outra biblioteca gslcblas que proporciona um conjunto de
rotinas de
algebra linear usadas pela gsl 2 , da que esta tenha de entrar tambem na fase do link.
Este nosso programa devolve ent
ao o resultado
$
./gsl-bessel
J0(5) = -1.775967713143382920e-01
(5.2)
(5.3)
o manual da gsl em info gsl Special Functions Bessel Functions Regular Cylindrical
Bessel Functions.
2 Basicamente, a gslcblas
e a conhecida BLAS re-escrita para a gsl
44
5.3. Geradores de N
umeros Aleat
orios
5.3. Geradores de N
umeros Aleat
orios
A gsl fornece uma extensa coleccao de geradores de n
umeros pseudo-aleatorios os quais podem ser
acedidos de uma forma universal, incluindo a escolha do gerador durante o tempo de execucao, o
que permite mudar de gerador facilmente sem ter de recompilar o programa. As funcoes nessarias
para este recurso s
ao definidas no header gsl rng.h. Esta generalidade tem um preco que, neste
caso, e o processo de inicializacao e definicao do gerador de n
umeros aleat
orios. Mais do que nos
outros, neste caso e melhor ver um exemplo:
/
F i l e g s l random . c
Exemplo de u t i l i z a c a o de g e r a d o r de numeros a l e a t o r i o s e n t r e [ 0 , 1 [
V i t o r M. P e r e i r a
/
11
13
#i n c l u d e < s t d i o . h>
#i n c l u d e < g s l / g s l r n g . h>
i n t main ( v o i d )
{
c o n s t g s l r n g t y p e T ;
gsl rng r ;
// Tipo de g e r a d o r
// P o i n t e r p a r a novo g e r a d o r
15
17
int i , n = 10;
double u ;
21
23
19
25
// D e f i n e o t i p o de g e r a d o r a u s a r
// A l o c a memoria p a r a o g e r a d o r
27
// I m p r i m e o t i p o de g e r a d o r u s a d o :
29
p r i n t f ( E i s 10 numeros g e r a d o s p e l o g e r a d o r % s \ n , g s l r n g n a m e ( r ) ) ;
31
// C a l c u l a e i m p r i m e 10 numeros a l e a t o r i o s :
33
35
f o r ( i = 0 ; i < n ; i ++)
{
u = gsl rng uniform ( r );
37
// D e v o l v e numero a l e a t o r i o e n t r e
// [ 0 , 1 [ u s a n d o o g e r a d o r r
p r i n t f ( %.5 f \n , u ) ;
39
41
// L i b e r t a a memoria a s s o c i a d a ao g e r a d o r
43
45
5. Topicos preliminares
return 0;
45
Listagem 5.2: N
umeros aleat
orios com a gsl (gsl-random.c)
Este c
odigo pode ser compilado com
$ gcc -Wall gsl-random.c -lgsl -lgslcblas -o gsl-random
(5.4)
e executado, obtendo-se:
$ ./gsl-random
Eis 10 numeros gerados pelo gerador mt19937
0.99974
0.16291
0.28262
0.94720
0.23166
0.48497
0.95748
0.74431
0.54004
0.73995
Esta sequencia de n
umeros foi gerada pelo gerador gsl rng mt19937, aquele que e escolhido por
omissao quando se definiu T = gsl rng default;. Claro que poderamos ter usado um outro
qualquer, entre os muitos que a gsl disponibiliza. Por exemplo, se quisessemos usar o gerador
odigo fonte.
ranlux bastaria, em vez de T = gsl rng default;, definir T = gsl rng ranlux; no c
Mas a gsl faz melhor do que isso! Ao usar T = gsl rng default; podemos escolher o gerador
durante a execucao, sem alterar o c
odigo fonte ne recompila-lo. Isso e feito por intermedio de
uma vari
avel de ambiente chamada GSL RNG TYPE que, pode ser definida pelo utilizador antes de
executar o programa. Esta vari
avel deve conter o gerador de n
umeros aleat
orios a usar. Por
exemplo o comando seguinte faz isso:
$ GSL_RNG_TYPE="ranlux" ./gsl-random
Eis 10 numeros gerados pelo gerador ranlux
0.53982
0.76155
0.06030
0.79600
0.30631
0.08278
0.66542
0.46075
0.92574
0.61915
46
Vemos que o gerador mudou (e, logo, muda a sequencia tambem), sem ser necess
ario tocar no
c
odigo fonte do programa. Do mesmo modo, e possvel escolher a semente durante o tempo de
execucao atraves da vari
avel de ambiente GSL RNG SEED. Por exemplo:
$ GSL_RNG_SEED=12345 ./gsl-random
Eis 10 numeros gerados pelo gerador mt19937
0.92962
0.89015
0.31638
0.13071
0.18392
0.03976
0.20456
0.82644
0.56773
0.53208
gera uma sequencia obviamente diferente da gerada acima com o mt19937.
5.4. Funco
es como argumentos
No uso de bibliotecas numericas cujas rotinas realizam tarefas como procurar um mnimo, determinar uma raz ou calcular um integral e frequente receberem como argumentos funcoes. Vejamos
um exemplo. A seguinte funcao tem dois argumentos. O segundo e uma vari
avel double. O
primeiro e uma funcao de argumento double que devolve double tambem.
iterate function(f, x)
Em C o nome de uma funcao e, de facto, um apontador para a funcao. Isso significa que a definicao
de iterate function tambem poderia ser feita como se segue:
47
5. Topicos preliminares
iterate function(f,x);
/* forma 1*/
iterate function (&f,x);
/* forma 2 */
5.5. Funco
es de n
umero de argumentos vari
avel
O mecanismo do par
agrafo anterior tem uma defeito grave. Suponhamos que queriamos iterar uma
funcao com dois argumentos:
48
5.5. Funcoes de n
umero de argumentos vari
avel
Este conceito permite construir tipos derivados de dados mais complexos que os nativos do C, e
constitui uma ferramenta essencial da linguagem em qualquer tarefa menos trivial de programacao.
Quando realizamos uma tarefa como procurar uma raz ou integrar a funcao singularizamos
um dos seus argumentos e tratamos os outros como par
ametros. Na biblioteca GSL usamos uma
struct (estrutura) com dois elementos. O primeiro elemento desta estrutura e a funcao, que tem
dois argumentos:
double (*function)(double x, void *params)
Note-se que o segundo argumento desta funcao e um apontador para void. Na definicao concreta
de uma funcao este apontador apontar
a para a lista de par
ametros. Por isso o seu tipo e void, o
que permitir
a sem conflitos fazer um cast (convers
ao explcita3 ) e apont
a-lo para qualquer tipo
de vari
avel. O segundo elemento da estrutura e precisamente este apontador, ao qual teremos que
aceder. Assim a construcao do tipo gsl function fica:
struct gsl function struct{
double (*function)(double x, void *params);
void *params;
};
typedef struct gsl function struct gsl function;
O uso de typedef permite simplificar declaracoes posteriores. Por exemplo:
gsl function F, *FF;
declara F como sendo uma estrutura acima descrita e FF um apontador para uma tal estrutura.
Vejamos agora como podemos definir uma instancia de uma funcao gsl function.
Eis o c
odigo para definir uma funcao de uma vari
avel e dois par
ametros:
/* Template para par de parametros */
struct pair{
double a1, a2;
};
/*
Funcao de uma variavel, com dois parametros
Note-se o template generico usado em gsl function
*/
double f(double x, void *params);
3 Se
i
e uma vari
avel do tipo int, ent
ao
(double) i
49
5. Topicos preliminares
double x = 1.;
/* Decalracao e inicializacao da estrutura pd */
struct pair pd = {0.5, 1.0};
void *pp = &pd;
f1 = f(x, pp);
5.6. A func
ao gsl function
Tendo visto como podemos incluir numa u
nica declaracao funcoes com n
umero arbitrario de
par
ametros vejamos agora como inicializar uma gsl function.
Como calcular o valor de uma gsl function? Eis dois processos equivalentes, um usando F e o
outro FF. Recorde-se que os membros de uma struct gsl function s
ao function e params.
50
f2 = (F.function)(x, (F.params));
f3 = (FF -> function)(x, (FF -> params));
A biblioteca GSL define uma macro com dois argumentos GSL FN EVAL(F,x) em que F e um apontador para uma gsl function e x o valor da vari
avel onde a funcao deve ser calculada. A macro
e:
#define GSL FN EVAL(F,x) (*((F) -> fuction))(x,(F) -> params)
Note-se que esta u
ltima express
ao e perfeitamente equivalente `a usada na atribuicao de f3.
51
5. Topicos preliminares
52
6. Exemplos
6.1. Minimizac
ao de Funco
es
Para ilustrar o uso desta biblioteca vamos agora apresentar um exemplo completo. Primeiro o
problema.
s(m) =
log
log
2
2
2
2
Eis o c
odigo destas funcoes. Note-se que usamos a forma da declaracao das funcoes gsl para o
funcional de campo medio:
73
75
77
79
81
83
double e n t r o p y ( double m)
{
i f ( f a b s (m) == 1 . )
return 0 . ;
else
r e t u r n 0.5(1.+m) l o g ( 0 . 5 ( 1 . +m)) 0.5(1. m) l o g ( 0 . 5 ( 1 . m) ) ;
}
double f m e a n f i e l d ( double m, v o i d params )
{
double temp , f i e l d ;
s t r u c t p a i r p = ( s t r u c t p a i r ) params ;
85
87
53
6. Exemplos
0.8
2.0
1.8
1.6
1.4
1.2
1.0
0.8
0.6
0.4
0.2
0.0
0.6
f(m)
0.4
0.2
-0.2
-0.4
-1
-0.5
0.5
Figura 6.1.: Funcional de energia livre em funcao da magnetizacao, para diferentes temperaturas
em campo nulo (h = 0).
89
energia
livre
para
uma
dada
magnetizacao
As funcoes de minimizacao da biblioteca usarao como argumento um apontador para uma gsl function,
aqui designada por F:
gsl function F;
F.function = &f mean field;
F.params = &pd;
Antes de prosseguir com a construcao do programa para minimizar o funcional de energia livre
convem ter uma imagem do seu comportamento. Consideremos o caso h = 0. Na fig. 6.1 est
a
representado o funcional de energia livre, subtrado do seu valor a magnetizacao nula f (m, T, 0)
f (0, T, 0), em funcao de m para varios valores de T .
6.1.2. Inicializac
ao
#i n c l u d e < s t d i o . h>
#i n c l u d e < s t d l i b . h>
54
11
13
#i n c l u d e <math . h>
#i n c l u d e < g s l / g s l e r r n o . h>
#i n c l u d e < g s l / g s l m i n . h>
#d e f i n e MAX ITER 10000
#d e f i n e TMIN 0 . 1
#d e f i n e TMAX 1 . 5
struct pair
{
double temp , f i e l d ;
};
15
17
19
21
23
25
27
29
double e n t r o p y ( double m) ;
double f m e a n f i e l d ( double m, v o i d params ) ;
i n t main ( )
{
int i , i t e r = 0 , status ;
c o n s t g s l m i n f m i n i m i z e r t y p e T ;
gsl min fminimizer s ;
double m = 0 . , temp ;
double a = 1. , b = 1 . ;
s t r u c t p a i r pd ;
gsl function F;
F . f u n c t i o n = &f m e a n f i e l d ;
F . params = &pd ;
31
33
35
pd . f i e l d = 0 . ;
37
39
41
43
45
47
49
51
53
55
f o r ( i = 0 ; i <= 1 0 0 ; ++i )
{
temp = TMIN + i (TMAX TMIN ) / 1 0 0 . ;
i f ( temp >= 1 . )
m = 0.;
else
m = 1 . 1 . e 8;
a = 1.;
b = 1.;
pd . temp = temp ;
g s l m i n f m i n i m i z e r s e t ( s , &F , m, a , b ) ;
do
{
++i t e r ;
status = gsl min fminimizer iterate ( s );
m = gsl min fminimizer x minimum ( s );
a = gsl min fminimizer x lower ( s );
b = gsl min fminimizer x upper ( s );
55
6. Exemplos
1.0
0.8
m(T)
0.6
0.4
0.2
0.0
0.0
1.0
0.5
1.5
57
59
61
63
65
}
gsl min fminimizer free (s );
67
69
return 0;
71
56
Parte IV.
Outros T
opicos
por Vtor M. Pereira
57
7. Argumentos ao main
7.1. argv e argc
Em computacao e muito frequente a situacao em que onde a execucao de um programa depende
de determinados par
ametros que dever
ao ser passados, por exemplo, pelo utilizador. Um exemplo
classico e quando se espera que o programa escreva algo para determinado ficheiro, cujo nome deve
ser definido durante a execucao. Uma das formas de implementar esse tipo de necessidade consiste
em usar os recursos de leitura do C , como sejam, as funcoes scanf(), getchar(), etc. Uma outra
forma de o fazer de modo bastante mais pratico e passar esses par
ametros como argumentos ao
main()1 .
Claro que, como o main() e chamado pelo sistema operativo, a u
nica forma de lhe passar
argumentos e atraves do sistema operativo, ou, na pratica, da shell. Passar um argumento ao
main() de um programa cujo execut
avel se chama prog e t
ao simples como
$ ./prog arg1 arg2 arg3
(7.1)
59
7. Argumentos ao main
/
F i l e show args . c
I m p r i m e t o d o s o s a r g u m e n t o s p a s s a d o s na l i n h a de comando
V i t o r M. P e r e i r a
/
#i n c l u d e < s t d i o . h>
#i n c l u d e < s t d l i b . h>
10
12
14
16
i n t main ( i n t a r g c , c h a r a r g v )
{
int i ;
f o r ( i =0; i <a r g c ; ++i )
p r i n t f ( a r g v [%d ] = %s \n , i , a r g v [ i ] ) ;
e x i t ( EXIT SUCCESS ) ;
}
60
7.2. Vari
aveis de ambiente
exemplo de uma aplicacao que usa os valores numericos dos argumentos e dado pelo problema 4
da folha de problemas Exerccios de linguagem C :
/
F i s i c a Computacional
E x e r c i c i o s de Linguagem C
V i t o r M. P e r e i r a ( Fev 2 0 0 6 )
/
/
4 . Imprima a soma de d o i s numeros p a s s a d o s na l i n h a de comandos .
Exemplo :
. / soma 2 3
2+3=5
11
13
15
17
19
21
/
#i n c l u d e < s t d i o . h>
#i n c l u d e < s t d l i b . h>
#i n c l u d e < a s s e r t . h>
i n t main ( i n t a r g c , c h a r a r g v [ ] )
{
int i i ;
double sum = 0 . 0 ;
23
/ So v a l e a pena p r o s s e g u i r s e h o u v e r p e l o menos 2 t e r m o s : /
25
p r i n t f ( \ n Here s y o u r r e s u l t : \ n\n ) ;
29
f o r ( i i = 1 ; i i < a r g c ; ++ i i ) {
sum += a t o f ( a r g v [ i i ] ) ;
p r i n t f ( %g + , a t o f ( a r g v [ i i ] ) ) ;
}
31
33
p r i n t f ( \ b\b = %g \n , sum ) ;
return 0;
35
37
7.2. Vari
aveis de ambiente
Finalmente, existe tambem com frequencia a necessidade de comunicar com um programa de
forma semi-permantente, sem ter o utilizador de estar sempre a definir o input. Claro que se
pode sempre criar um ficheiro de configuracao que ser
a lida pelo programa, e esse e o modo mais
61
7. Argumentos ao main
/
F ile environ . c
D emonstracao da u t i l i z a c a o de v a r i a v e i s de a m b i e n t e
V i t o r M. P e r e i r a
/
#i n c l u d e < s t d i o . h>
#i n c l u d e < s t d l i b . h>
10
12
i n t main ( i n t a r g c , c h a r a r g v [ ] , c h a r envp [ ] )
{
c h a r u s e r , home , h o s t ;
14
p r i n t f ( T e r c e i r a v a r i a v e l de a m b i e n t e : %s \n\n , envp [ 3 ] ) ;
16
home = g e t e n v ( HOME ) ;
h o s t = g e t e n v ( HOSTNAME ) ;
u s e r = g e t e n v ( USER ) ;
18
20
p r i n t f ( Ola %s , b e n v i d o a maquina %s . \ n , u s e r , h o s t ) ;
p r i n t f ( A s u a home e s t a em %s . \ n , home ) ;
22
return 0;
24
A listagem acima mostra um exmplo de aplicacao que recorre inicialmente ao vector de vari
aveis
de ambiente, imprimindo uma delas (a terceira, neste caso), e depois, acede ao conte
udo de outras
3 vari
aveis especficas. No meu sistema, este programa devolve o seguinte:
$ ./environ
3 Esta
utilizaca
o do main() com mais de dois argumentos n
ao
e standard. Trata-se de uma extens
ao do gcc . No
entanto, o uso de getenv(), etc. descrito abaixo
e standard.
62
7.2. Vari
aveis de ambiente
63
7. Argumentos ao main
64
A. Lista de Comandos
Lista e descricao sum
aria dos programas mais relevante referidos neste documento. A mior parte
deles constituem os chamados GNU binnary utils (binutils). Informacao detalhada pode ser sempre
obtida nas p
aginas do manual correspondente, ou atraves do info binutils. Abaixo deixamos
apenas a descricao tal como devolvida pelo whatis.
ar
as
g77
gcc
ldd
ld
make
nm
wc
65
A. Lista de Comandos
66
Bibliografia
[1] Peter Prinz and Ulla Kirch-Prinz, C Pocket Reference, OReilly, 2002.
[2] Brian J. Gough, An Introduction to GCC - for the GNU compilers gcc and g++, Network
Theory Ltd, 2004.
[3] Richard Stalman, The GNU make Manual (info make), Version 3.80, 2002.
[4] The GNU C Manual (info gcc), Version 4.1.0, 2006.
[5] The GNU Scientific Library Reference Manual (info gsl), Version 1.7, 2006.
[6] The GNU binary utilities (info binutils), Version 2.16.91.0.6, 2006.
[7] Al Kelley and Ira Pohl, A Book on C: programming in C, Addison-Wesley, 4th ed., 2001.
[8] P. M. Chaikin and T. C. Lubensky, Principles of condensed matter physics, Cambridge
University Press, 1995.
67