Transcript
Page 1: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

1

Prof. Alessandro Garcia

Eduardo Fernandes (assistente)

LES/DI/PUC-Rio

Abril 2018

Aula 12

Implementação da Programação Modular

Especificação

• Objetivo dessa aula

– Visão geral sobre compilação de programas modulares

– Estudar em detalhe a composição generalizada de módulos

– Estudar o uso de ponteiros

• Slides adaptados de: Staa, A.v. Notas de Aula em Programação

Modular; 2008.

• Referência básica:

– Capítulos 6, 8 e Apêndice 7 do livro texto

• Referência complementar:

– Schildt H. C – Completo e Total, 3ª Edição. Makron Books,

1997.

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 2 /37

Page 2: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

2

Sumário

• Pilha de execução e classes de memória

• Ligação, pré-processamento e compilação

• Composição de módulos e estrutura de diretórios

• Referências, funções de acesso

• Função como dado

• Variáveis ponteiro para função

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 3 /37

Classes de memória real

• Executável

– é onde se armazena o código a ser executado e, possivelmente,

algumas constantes numéricas

• Estática encapsulada

– contém todos os espaços de dados globais encapsulados (declarados

static), e todas as constantes literais definidas no interior de módulos

• Estática visível

– contém todos os espaços de dados globais externados

• Automática

– contém a pilha de execução do programa

• Dinâmica

– contém espaços de dados alocados pelo usuário (malloc, new)

• Persistente

– é onde se armazenam os dados que estarão disponíveis de uma

instância de execução do programa para outra

• arquivos contendo parâmetros de execução: arquivos .dat e .ini

• bases de dados

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 4 /37

Page 3: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

3

Processo de compilação simples (Ligação)

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio

Compilador

Compilador

Compilador

Ligador

M3.OBJ

M2.OBJ

M1.OBJ

L2.LIB

L1.LIB

PG.EXE

Editor deprogramas

M3.HPP

M3.CPP

M2.HPP

M2.CPP

M1.HPP

M1.CPP

Programa

5 /37

Ligação

• A ligação combina m >= 1 módulos objeto e módulos

contidos em uma ou mais bibliotecas, produzindo o

programa carregável (.EXE, .COM)

• No módulo objeto todos os endereços gerados são

deslocamentos (offsets) relativos a zero dentro da

respectiva classe de memória

• O ligador (linker) justapõe (concatena) os espaços de cada

uma das classes de memória (segmentos: executável e

estática) definidos nos módulos objeto, formando um único

grande espaço para cada classe de memória

• Estes dois grandes segmentos constituem o programa

carregável

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 6 /37

Page 4: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

4

Composição de um módulo objeto

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio

Dados

estáticos

Código

Tab Simb

M1.OBJ

Declarados e definidos, relativos a 0

Tabela de símbolos- referências a nomes externos declarados e não definidos - referências a nomes externos declarados e definidos (externados pelo módulo)

(importados)

Relocável, relativo a 0

Tab Reloc Tabela de relocação- informa os locais contendo endereços a serem relocados

7 /37

Símbolos definidos no módulo objeto

• Cada módulo objeto contém uma tabela de símbolos

agregando os nomes globais externos, particionada em

– símbolos somente declarados

– símbolos declarados e definidos

• Os símbolos somente declarados definem uma lista de todos

os locais no código (ou nos dados) em que o símbolo é

referenciado

• Um nome externo somente declarado em um determinado

módulo necessariamente deverá estar declarado e definido

em exatamente um outro módulo do programa sendo

composto

– i.e. cada nome deve ser definido em um único módulo

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 8 /37

Page 5: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

5

Processo de compilação simples

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio

Compilador

Compilador

Compilador

Ligador

M3.OBJ

M2.OBJ

M1.OBJ

L2.LIB

L1.LIB

PG.EXE

Editor deprogramas

M3.HPP

M3.CPP

M2.HPP

M2.CPP

M1.HPP

M1.CPP

Programa

9 /37

Composição de um executável

Passos

1. concatenar os módulos objeto

– código e dados estáticos

2. relocar os endereços do

módulo de modo que estejam

em conformidade com a

origem na concatenação

3. resolver os nomes externos ao

módulo definidos em outro

módulo

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio

p.exe

código dados estáticos

0

300

530

0

10

30

m1

m2

m3

m1

m2

m3

int a

int b

int c

a

a

b

c

10 /37

Page 6: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

6

Relocação

• O ligador ajusta os endereços dos elementos contidos em

cada segmento de modo que passem a ser deslocamentos

relativos à origem dos correspondentes segmentos do

programa

• A relocação ocorre com relação aos segmentos

– código

– estático local e externo

• A tabela de relocação contida no módulo objeto informa os

pontos no código e nos dados globais do módulo que

deverão ser ajustados

– no módulo objeto os deslocamentos são relativos a zero

– para relocar basta somar a origem do segmento do módulo

definida no segmento composto às referências internas ao

módulo registradas na tabela de relocação

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 11 /37

Resolução de nomes externos, sem bibliotecas

• O ligador cria uma tabela de símbolos que conterá os nomes externos. Cada símbolo informa

– o endereço no segmento composto

– a lista dos locais que referenciam o símbolo ainda não definidos

• Ao encontrar um nome externo

– adiciona-o à tabela caso ainda não figure lá

– se for um nome externo declarado e definido

• se a tabela de símbolos do ligador já define o nome, é emitido um erro de duplicação de definição

• caso contrário, percorre a lista dos locais que referenciam o símbolo e atribui o endereço definido

– se for um nome externo somente declarado

• se a tabela de símbolos do ligador já define o nome, atribui esta definição aos locais no módulo que referenciam este símbolo

• caso contrário, o ligador acrescenta a lista do módulo à lista do ligador

• Ao terminar o processamento

– para cada símbolo não definido contido na tabela do ligador, é emitido um erro de símbolo não definido

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 12 /37

Page 7: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

7

Resolução de nomes externos, com bibliotecas

• Uma biblioteca estática (.lib) é formado por

– uma lista de módulos

– uma tabela de símbolos contendo os símbolos externados pelos

módulos e a referência para o código do respectivo módulo na

lista de módulos

• Após compor todos os módulos objeto, para cada símbolo

ainda não definido

– o ligador procura este símbolo, segundo a ordem de

fornecimento das bibliotecas

• caso seja encontrado, o módulo correspondente é extraído da

biblioteca e acrescentado ao programa sendo montado

– para isso segue o procedimento anterior

• caso não seja encontrado, é emitido um erro de símbolo não

definido

– repete até todos os símbolos terem sido processados

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 13 /37

Ligação dinâmica

• Bibliotecas dinâmicas (.dll) são carregadas à medida que

forem acessadas durante o processamento

– ao encontrar um símbolo externo ainda não resolvido

• utiliza a .dll, se já carregada, ou então carrega ela

• substitui a referência ao símbolo para a referência à função

– cada biblioteca é compartilhada por todos os programas que a

usem

– cada programa estabelece espaços próprios para os dados

• Vantagens

– uma biblioteca dinâmica é carregada uma única vez

considerando todos os programas em execução simultânea

– pode-se trocar uma biblioteca sem precisar recompilar ou

religar todo o programa

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 14 /37

Page 8: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

8

Ligação dinâmica

• Problemas

– precisa-se projetar com muito cuidado as bibliotecas

dinâmicas, visando explicitamente a possibilidade do seu reúso

em diversos programas

– as bibliotecas são conhecidas pelo nome, portanto pode ocorrer

colisão de nomes

• bibliotecas diferentes com o mesmo nome

– é necessário assegurar que a versão correta da biblioteca seja

utilizada com cada um dos programas

• todos os programas utilizam a mesma versão da biblioteca, a

menos que se possa armazenar as bibliotecas em locais distintos

• todos evoluem à medida que as bibliotecas forem evoluindo

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 15 /37

Carga de um programa

• Para poderem ser executados, programas precisam estar

em memória real

– fragmentos de um programa executável podem estar em

qualquer um dos segmentos: executável, pilha (automático),

estático, e dinâmico. A origem estará no segmento executável.

• Ao ativar um programa, é ativado o carregador que recebe

como parâmetro o nome do arquivo contendo o programa a

ser carregado

• O carregador

– determina onde serão colocados os segmentos executável e

estático e copia os segmentos do arquivo para a memória

– efetua as necessárias relocações de modo a ajustar os

endereços contidos nesses segmentos

– ativa o programa chamando a função main( ) (ou winmain( ))

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 16 /37

Page 9: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

9

Pré-processamento

• Um pré-processador

– é um processador de linguagem

– recebe um arquivo contendo texto fonte e diretivas de pré-

processamento

– produz um outro arquivo de texto fonte na mesma linguagem

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 17 /37

Padrão de programação C

• Ao desenvolver programas em C ou C++ siga o

recomendado no apêndice 1 Padrão de Composição de

Módulos C e C++.

• Todos os módulos que podem ser incluídos devem conter

um controle de compilação única

– módulo de definição

– tabelas de definição

– tabelas de dados

#if !defined( Nome-arquivo_MOD )

#define Nome-arquivo_MOD

/* Comentário cabeçalho do arquivo */

Corpo do arquivo

#endif

/* Comentário fim de arquivo*/

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 18 /37

Page 10: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

10

Consistência das interfaces C/C++

• Problema devido a propriedades sintáticas das linguagens

C/C++

– variáveis globais externas devem aparecer exatamente uma

vez sem o declarador extern

– todas as outras vezes devem vir precedidas deste declarador

• Pode-se conseguir isso com código de pré-processamento

que assegure

– sempre que um cliente compilar o módulo de definição, as

declarações de variáveis globais externas estejam precedidas

de extern

– sempre que o próprio módulo compilar o módulo de definição,

as variáveis globais externas não estejam precedidas de

extern

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 19 /37

Padrão para o módulo de definição

• Inicie o código do corpo do módulo de definição com o

seguinte esquema de código:

/* Controle de escopo do arquivo de definição */

#ifdef Nome-arquivo-modulo_OWN

#define Nome-arquivo-modulo_EXT

#else

#define Nome-arquivo-modulo_EXT extern

#endif

• Ao final do código do módulo de definição coloque o código:

#undef Nome-arquivo-modulo_EXT

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 20 /37

Page 11: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

11

Padrão para o módulo de definição

• Declare cada variável global externa não inicializada da

seguinte forma:

Nome-arquivo-modulo_EXT declaração-de-variável ;

• Declare cada variável global externa inicializada da seguinte

forma

Nome-arquivo-modulo_EXT declaração-variavel

#ifdef Nome-arquivo-modulo_OWN

= Inicialização ;

#else

;

#endif

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 21 /37

Exemplo de módulo de definição

#ifndef EXEMP_MOD

#define EXEMP_MOD

#ifdef EXEMP_OWN

#define EXEMP_EXT

#else

#define EXEMP_EXT extern

#endif

/***** Tipo de dados exportado pelo módulo *****/

typedef struct

{

int UmInt ;

int OutroInt ;

} EX_tpMeuTipo ; /* declaração de tipos não é afetada pelas regras */

/***** Estruturas de dados exportada pelo módulo *****/

EXEMP_EXT int EX_vtNum[ 5 ]

#if defined( EXEMP_OWN )

= { 1 , 2 , 3 , 4 , 5 } ;

#else

;

#endif

#undef EXEMP_EXT

#endif

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 22 /37

Page 12: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

12

Padrão para o módulo de implementação

• No módulo de implementação, redija o código de inclusão do

respectivo módulo de definição na forma a seguir:

#define Nome-Arquivo-Modulo_OWN

#include "Nome-Arquivo-Modulo.H"

#undef Nome-Arquivo-Modulo_OWN

• Exemplo

/* Inclusões do compilador /

#include <stdio.h>

/* Inclusão do próprio módulo de definição /

#define EXEMP_OWN

#include "EXEMP.H"

#undef EXEMP_OWN

/* Inclusão de módulos de definição de servidores */

#include "Modulo1.H"

#include "Modulo2.H"

#include "Tabela.INC"

. . .

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 23 /37

Estrutura de diretórios (pastas)

• É fortemente recomendável criar uma estrutura de

diretórios (pastas) padrão para cada projeto

– pastas com menos arquivos são mais fáceis de manipular

– cada pasta conterá arquivos de alguns poucos tipos

– Exemplo: autotest/instrum

+ Projeto X

+ Batches contém arquivos .bat

+ Composicao contém arquivos .make, .comp, ...

+ ModulosFonte contém arquivos .c, .h, ...

+ ModulosObjeto contém arquivos .obj, .build, ...

+ Produto contém arquivos .exe, .log, ...

+ Tabelas contém arquivos .tabstr, .incstr, ...

+ Teste contém arquivos .script, .count, ...

+ ... (por exemplo os de apoio ao ambiente)

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 24 /37

Page 13: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

13

O que são referências?

• Uma referência é formada por um conjunto de parâmetros a

serem fornecidas a uma função de acesso para acessar um

determinado espaço

– exemplo: elemento de um vetor em C

< origemVetor , dimElemento , inxElemento >

– exemplo: disco físico

< unidade , cilindro , trilha , setor >

– exemplo: arquivo

< pArq , inxByte , idOrigem >

• Cada classe de referência possui uma função de acesso

associada a ela

– exemplo vetor: tpX vtX[ dimVtX ] ; ... vtX[ i ] ...

– exemplo disco físico: um serviço do sistema operacional

– exemplo arquivo: fseek( , , )

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 25 /37

Dereferenciação

• Dereferenciar é a operação de converter uma referência em

um endereço real através de sua função de acesso,

exemplos: (obs.: não são fragmentos de código em C)

– A[j] :: &A + j * sizeof( tpA ) – tudo medido em bytes

– *pX :: [ pX ] ou por extenso: conteúdo de pX

– seja: pElemTabSimb * ObterElemTabSimb(

char * pszSimbolo)

• *( ObterElemTabSimb( "um_simbolo" ))

– é o espaço de dados associado ao símbolo "um_simbolo“

• :: operador “é definido por”

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio

operador de dereferenciação

de ponteiro

expressão gera um ponteiro

26 /37

Page 14: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

14

Dereferenciação

• A dereferenciação pode ser realizada até chegar ao valor

expA = expB

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio

RHS

right hand side

LHS

left hand side

busca-se o valor referenciado

pelo endereço RHS

i.e. dereferencia-se o

endereço RHS

atribui-se o valor RHS

ao endereço LHS

27 /37

Dereferenciação composta

• Assumindo que os espaços de dados referenciados existam:

typedef struct tgElemLista

{

char szSimbolo[ DIM_SIMBOLO ] ;

unsigned IdSimbolo ;

struct tgElemLista * pProx;

} tpElemLista ;

tpElemLista * Tabela[ DIM_TABELA ] ;

( Tabela[ ObterHash( szSimboloDado )]->pProx)->szSimbolo

ou

*(*( Tabela[ ObterHash( szSimboloDado )]).pProx ).szSimbolo

• acessam o mesmo vetor de caracteres – o segundo

elemento da lista

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 28 /37

Page 15: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

15

Ponteiros

• Ponteiros são casos especiais de referências

– função de acesso é implícita: *pX :: conteúdo de pX

• Há quem prefira outra definição de modo que se caracterize

o controle que se pode ter quando se usa referências,

contrastando com a falta de controle quando se usa

ponteiros, exemplo

– vtA[ inxA ] ::

• if (( inxA < 0 ) || ( inxA >= dimA ))

ErroAcesso( __FILE__ , __ LINE__) ;

– pA[ inxA ] :: ??? pois não se sabe o valor de dimA

– pA + inxA :: ??? idem

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 29 /37

Ponteiros – Problemas comuns

• Vazamento de Memória:

– Retornar de função sem destruir espaços de memória (não

encadeados em alguma estrutura) referenciados por ponteiros

locais

• Falha de Segmentação:

– Dereferenciar ponteiro com valor NULL

– Dereferenciar ponteiro não inicializado

– Dereferenciar ponteiro cujo espaço de memória foi destruído

(free/delete)

• Apêndice 7: regras e recomendações para o uso de

ponteiros

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 30 /37

Page 16: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

16

Ponteiro para função

• Funções possuem:

– Um tipo

– Um espaço de dados que é ocupado pelo código da função

– Um nome que referencia esse espaço de dados

• Em C é possível criar variáveis e parâmetros do tipo

“Ponteiro para função”:

int soma (int a, int b) {

return a + b;

}

int main () {

int (*operacao) (int, int);

operacao = soma;

operacao(1, 2);

}

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 31 /37

Abr 2018 32 /37

Função como um dado

• O tipo de uma função é estabelecido pela sua assinatura

física

– valor retornado

– lista dos tipos de parâmetros

• os nomes dos parâmetros não fazem parte da assinatura

• o nome da função não faz parte da assinatura

– exemplo: int ( int , double )

– exemplo: tpHistórico * ( tpIdAluno )

• Uma função A será do mesmo tipo que a função B caso

ambas tenham a mesma assinatura

– note que não se pergunta o que a função faz – semântica

– no entanto deveria existir uma “igualdade” semântica

Alessandro Garcia © LES/DI/PUC-Rio

Page 17: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

17

Abr 2018 33 /37

Dado tipo ponteiro para função

• Em C e C++ podem ser definidas variáveis do tipo ponteiro

para função

– exemplo: int (* VarF1 )( int , double )

• VarF1 é um ponteiro para função do tipo: int ( int , double )

– exemplo: tpHist * (* VarF2 )( tpIdAl )

• VarF2 é um ponteiro para função do tipo: tpHist * ( tpIdAl )

– Exemplo de atribuição

int Func( int X , double Y )

{

...

} /* Func */

VarF1 = Func ;

Func é uma constante do tipo

ponteiro para uma função do tipo:int ( int , double )

Alessandro Garcia © LES/DI/PUC-Rio

Abr 2018 34 /37

Exemplo simples: integração

/* Função de integração numérica utilizando regra dos trapézios */

double Integrar( double LimInf ,

double LimSup ,

int NumInt ,

double ( * Func )( double X ))

{

double Integral = 0.0 ;

double Intervalo ;

int i ;

assert( NumInt >= 2 ) ;

Intervalo = ( LimSup - LimInf ) /

( NumInt - 1 ) ;

Integral += Func( LimInf ) ;

Integral += Func( LimSup ) ;

Integral /= 2.0 ;

for ( i = 1 ; i < NumInt - 1 ; i++ )

{

Integral += Func( Intervalo * i ) ;

} /* for */

Integral *= Intervalo ;

return Integral ;

} /* Integrar */

A B

Y

X

0 1 2 3 4 5 6 7 8

Alessandro Garcia © LES/DI/PUC-Rio

Page 18: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

18

Abr 2018 35 /37

Exemplo simples: integração, uso

/* exemplo de uso */

double Quadrado( double X )

{

return X ** 2 ;

}

double Cubo( double X )

{

return X ** 3 ;

}

printf( ″\n F = x ** 2 de x=1 a x=10: %lf″ ,

Integrar( 1.0 , 10.0 , 20 , Quadrado )) ;

printf( ″\n F = x ** 3 de x=1 a x=10: %lf″ ,

Integrar( 1.0 , 10.0 , 20 , Cubo )) ;

Alessandro Garcia © LES/DI/PUC-Rio

Ponteiro para função

• Ver exemplo autotest\lista na função de criação de Lista

Abr 2018 Alessandro Garcia © LES/DI/PUC-Rio 36 /37

Page 19: Aula 12 Implementação da Programação Modularinf1301/docs/2018_1/aula_12.pdf · M3.CPP M2.HPP M2.CPP M1.HPP M1.CPP Programa 5 /37 Ligação • A ligação combina m >= 1 módulos

19

Prof. Alessandro Garcia

Eduardo Fernandes (assistente)

LES/DI/PUC-Rio

Abril 2018

Aula 12

Implementação da Programação Modular


Top Related