segunda-feira, 8 de junho de 2009

SUBPROGRAMAS


Subprogramas são blocos de construção fundamentais de programas e, portanto, estão entre os conceitos mais importantes no projeto de linguagens de programação.


Introdução:
Duas facilidades de abstração fundamentais podem ser incluídas em uma linguagem de programação: abstração de processos e abstração de dados.
O primeiro computador programável, a Máquina Analítica de Babbage, construída na década de 1980, tinha capacidade de reutilizar coleções de cartões de instruções em diversos lugares diferentes em um programa quando isso era conveniente. Em uma linguagem de programação moderna, essa coleção de instruções era escrita como um subprograma. Tal reutilização resulta em diversos tipos diferentes de economia, de espaço de memória a tempo de codificação.




Características gerais do subprograma:
Cada subprograma tem um único ponto de entrada.
Toda unidade de programa chamadora é suspensa durante a execução do programa chamado, o que implica na existência de somente um subprograma em execução em qualquer momento dado.
O controle sempre torna ao chamador quando a execução do subprograma encerra-se
Definições básicas:
Uma definição de subprograma descreve a interface e as ações da abstração de subprograma. Uma chamada a subprograma é a solicitação explícita para executar o programa. Diz-se que um subprograma é ativo se, depois de ter sido chamado, ele iniciou a execução, mas ainda não a concluiu.
Um cabeçalho de subprograma, a primeira linha da definição, serve a diversos propósitos, como especificando que a unidade sintática seguinte é uma definição de subprograma de algum tipo particular.
void adder (parâmetros)
serviria como o cabeçalho de uma função chamada adder, em que void indica que ela não retorna um valor.
O perfil parâmetro de um subprograma é o número, a ordem e o tipo de seus parâmetros formais. O protocolo de um subprograma é seu perfil de parâmetros mais, se for uma função, seu tipo de retorno. Em linguagens em que os subprogramas tem tipos, estes são definidos pelo protocolo do subprograma.
As declarações do subprograma são comuns em programas C, onde são chamadas de protótipos. Elas também são usadas na Ada e no Pascal, nas quais, às vezes, são chamadas de declarações forward ou externas.

Parâmetros
Os subprogramas tipicamente descrevem computações. Há duas maneiras pelas quais um subprograma pode ganhar acesso aos dados que devem processar: pelo o acesso direta a variáveis não-locais ou pela passagem de parâmetros.
Em algumas situações, é conveniente ser capaz de transmitir computações, em dedados, como parâmetros a subprogramas.
Os parâmetros no cabeçalho de subprograma são chamados de parâmetros formais. Por vezes, recebe o nome de variáveis burras, porque não as são no sentido usual: em alguns casos, vinculam-se no armazenamento somente quando o subprograma é chamado o que frequentemente se dá em algumas variáveis de programa.
As instruções de chamada a subprogramas incluem o nome dele uma lista de parâmetros a serem vinculados a seus formais. Esses parâmetros são chamados de reais.
Em quase todas as linguagens de programação, a correspondência entre parâmetros reais e formais – ou a vinculação de ambos – é feita simplesmente pela posição: o primeiro parâmetro real é vinculado ao primeiro formal e assim por diante. Eles são chamados de parâmetros posicionais.
Quando as listas são longas, o escritor do programa pode cometer mais erros quanto à ordem de parâmetros da lista. Uma solução para o problema é fornecer parâmetros nomeados, nos quais o nome do parâmetro formal a que um parâmetro real deve estar vinculado é especificado com este último.

Procedimentos e funções
Há duas categorias distintas de subprogramas: Procedimentos (procedures) e funções: ambos podem ser vistos como abordagens para estender a linguagem. Procedimentos são coleções de instruções que definem computações parametrizadas. Estas, por sua vez, são ativadas por instruções de chamadas simples.
As funções lembram estruturalmente os procedimentos, mas são semanticamente modeladas em funções matemáticas. Se uma delas for um modelo confiável, não produzirá nenhum efeito colateral; ou seja, a função não modificará seus parâmetros, nem quaisquer variáveis definidas fora dela.
As funções definem novos operadores determinados pelo usuário. Por exemplo, se uma linguagem não tiver um operador de exponenciação, pode-se escrever uma função que retorna o valor de um de seus parâmetros elevado à potência de outro.
Por exemplo, considere o seguinte cabeçalho de função e de chamada:
void sort (int list[], int listlen);
...
sort (scores, 100);
Os métodos do Java e do C++ são similares ao do C.

Questões de projeto referentes aos subprogramas
Subprogramas são estruturas complexas nas linguagens de programação. Isto quer dizer que uma extensa lista de questões está envolvida em seu projeto. Uma questão evidente é a escolha do método ou dos métodos de passagem de parâmetros a serem usados.
Ambientes de referências locais
Os subprogramas geralmente tem permissão para definir suas próprias variáveis, definindo assim, os ambientes de referência locais. Variáveis que são definidas dentro do subprograma são chamadas variáveis locais, porque o acesso a elas normalmente é restrito ao subprograma no qual são definidas.
No ALGOL 60 e em suas linguagens descendentes, as variáveis locais em um subprograma são, como padrão, stack-dinâmicas. Em funções C e C++, as variáveis locais são stack-dinâmicas, a menos que seja especificamente declaradas como static. Por exemplo, na seguinte função C (ou C++), a variável soma é estática e cont é stack-dinâmica.
Int somador (int list[], int listlen)
{
Static int soma = 0
Int cont;
For (cont= 0; <>
Métodos de passagem de parâmetros
Os métodos de passagem de parâmetros são as maneiras pelas quais se transmitem parâmetros para subprogramas chamados e/ou de subprograma chamados
Modelos semânticos de passagem de parâmetros
Os parâmetros formais são caracterizados por três modelos semânticos distintos:
1-eles podem receber dados do parâmetro real correspondente;
2-podem transmitir dados ao parâmetro real;
3-podem fazer ambos
Os três modelos semânticos são chamados modo entrada (in mode), modo saída (out mode) e modo entrada/saída (inout mode), respectivamente.
Passagem de parâmetros por valor
Quando um parâmetro é passado por valor, o valor do parâmetro real é usado para inicializar o parâmetro formal correspondente que, então age como uma variável local no subprograma, implementando assim, a semântica de modo de entrada.
Passagem de parâmetros por resultado
A passagem por resultado é um modelo de implementação para parâmetros em modo saída. Quando um parâmetro é passado por resultado, nenhum valor é transmitido para o subprograma.
Passagem de parâmetros por valor-resultado
A passagem por valor-resultado é um modelo de implementação de parâmetros em modo entrada/saída no qual valores reais são transferidos. Ela é, com efeito, uma combinação de passagem por valor e por resultado.
Passagem de parâmetros por referência
A passagem por referência é o segundo modelo de implementação de parâmetros em modo entrada/saída. Entretanto, em vez de transmitir valores de dados para lá e para cá, como na passagem de valor-resultado, o método de passagem por referência transmite um caminho de acesso, usualmente apenas um endereço, para o subprograma chamado. Isso proporciona o caminho de acesso à célula que armazena o parâmetro real.
A vantagem da passagem por referência é que o próprio processo de passagem é eficiente, tanto em termos de tempo como de espaço. Não é necessário espaço duplicado, nem qualquer atividade de cópia.
Passagem de parâmetros por nome
A passagem por nome é um método de transmissão de parâmetros em modo entrada/saída que não corresponde a um único modelo de implementação. Quando parâmetros são passados por nome, o parâmetro real é, com efeito, textualmente substituído para o parâmetro formal que corresponde em todas as suas ocorrências no subprograma.
Métodos de passagem de parâmetros das principais linguagens
O FORTRAN sempre usou o modelo semântico de modo entrada/saída para a passagem de parâmetros.
O ALGOL introduziu o método de passagem por nome.
O C usa passagem por valor. Obtêm-se a semântica da passagem por referência usando ponteiros como parâmetros.
O C++ inclui um tipo de ponteiro especial, chamado tipo de referência, entre outras linguagens.
Parâmetros de verificação de tipos
Agora é amplamente aceito que a confiabilidade de software exige que os tipos de parâmetros reais sejam verificados quanto à coerência com os tipos dos parâmetros formais correspondentes.
Arrays multidimensionais como parâmetros
as funções de associação de armazenamento são usadas para associar os valores de índice das referências a elementos de arrays multidimensionais a endereços na memória. Podemos ilustrar:
void fun (int matriz[] [])
{
...
}
Void main ()
{
Int mat [] [];
...
Fun (mat);

}

Considerações de projeto
Das importantes considerações estão envolvidas na escolha de métodos de passagem de parâmetros: eficiência, e se é necessária uma transferência unidirecional ou bidirecional de dados.
Parâmetros que são nomes de subprogramas
Ocorre um grande número de situações em programação mais convenientementes manipuladas se nomes de subprograma puderem ser enviados como parâmetros a outros subprogramas. Uma das mais comuns ocorre quando um subprograma precisa provar alguma função matemática. Por exemplo, um subprograma queue faz integração numérica estima a area sob o gráfico de uma função provando-a em uma série de diferentes pontos.
Subprogramas sobrecarregados
Um operador sobrecarregado é o que tem múltiplos significados. O significado de uma instância particular de um operador sobrecarregado é determinado pelos typos de sues operands. Por exemplo, se o operador * tiver dois operados de ponto flutuante em um programa C, isso especificará uma multiplicação de ponto-flutuante. Mas, se o mesmo operador tiver dois operados inteiros, isso especificará uma multiplicação de números inteiros.
Um subprograma sobrecarregado tem o mesmo nome que outro no mesmo ambiente de referênciamento.
Subprogramas genéricos
Um subprograma genérico ou polimórfico leva parâmetros de diferentes tipos em várias ativações. Os subprogramas sobrecarregados apresentam uma espécie particular de polimorfismo chamado polimorfismo ad hoc. Um tipo mais geral deste último é apresentado pelas funções da APL. Por causa da vinculação dinâmica de tipos da APL, os tipos de parâmetros podem permanecer sem ser especificados; eles simplesmente são vinculados ao tipo de parâmetros reais correspondentes.
Subprogramas genéricos em Ada
A Ada apresenta um poliformismo paramétrico por meio de uma construção que suporta a criação de múltiplas versões de unidades de programa para aceitar parâmetros de diferentes tipos de dados.
Uma vez que as unidades de programas desse tipo são genéricas por natureza, às vezes elas são chamadas unidades genéricas.
A classificação genérica nada mais é do que um modelo para um procedimento.
Lembre-se de que a Ada não permite que subprogramas sejam passados a outros subprogramas.
Funções genéricas em C++
As funções genéricas em C++ tem o nome descritivo de funções modelo. A definição de uma função modelo tem a forma geral:
Template <>
- Uma definição de função que pode incluir os parametros da classe
Cada parametro da classe tem a forma
Class identificador
Compilação separada e independente
A capacidade de compilar parte de um programa sem a necessidade de compilá-lo por inteiro é fundamental para a construção de sistemas de software grandes. Com essa capacidade, somente os módulos de um sistema em modificação pão pecisam ser recompilados durante o desenvolvimento e manipulação.
Existem duas abordagens distintas para compilar partes de um programa. O termo compilação separada significa que as unidades de compilação podem ser compiladas em tempos diferentes, mas elas não são independentes uma da outra. Em algumas linguagens, mais notavelmente no C e no FORTRAN 77, a compilação independente é permitida; com ela as unidades de programa podem ser compiladas sem informações sobre quaisquer outras unidades de programas.
A característica mais importante da compilação independente é que as interfaces entre as unidades compiladas separadamente não são verificadas quanto à coerência de tipos.
Efeitos colaterais funcionais
Devido aos problemas dos efeitos colaterais de funções que são chamadas em expressões, os parâmetros para funções sempre devem estar em modo de entrada (in mode).
Tipos de valores retornados
A maioria das linguagens de programação imperativas restringem os tipos que podem ser retornados por suas funções.
A Ada está sozinha entre as linguagens imperativa em termos que suas funções podem retornar
valores de qualquer tipo.
Acessando ambientes não-locais
As variáveis não-locais (escopo ecstatic e o scoop dynamic) de um subprograma são visíveis dentro dele, ma’s não declaradas localmente. As variáveis globais são visíveis em todas as unidades de programa.
O principal problema de usar o escopo estático como o meio de compartilhar variáveis não-locais é o seguinte: uma boa quantidade da estrutura do programa pode ser ditada pela acessibilidade de subprogramas e de variáveis não-locais a outros subprogramas, em vez de soluções de problema bem trabalhadas.
Dois tipos de problemas decorrem do escopo dinâmico. Primeiro, durante o intervalo de tempo que se inicia quando a execução de subprograma é iniciada e que se encerra quando é finalizada, as variáveis locais do subprograma são visíveis a quaisquer outros subprogramas em execução, independente da proximidade textual deles. O segundo é a incapacidade de fazer estaticamente a verificação de tipos de referências a não-locais.
Blocos COMMON do FORTRAN
O FORTRAN oferece acessos a blocos de armazenamento global por meio de sua instrução COMMON. Pode haver qualquer número desses blocos, sendo que todos, menos um, devem ser nomeados. Um bloco comum é criado quando a primeira instrução COMMON que menciona o nome dele é encontrado pelo compilador.
Na maioria dos casos, os dados em bloco COMMON devem ser compartilhados usando os mesmos nomes e tipos de variável.
A definição do FORTRAN 90 declara que COMMON é um dos “recursos desaprovados”, o que significa que ela pode ser incluída em somente mais uma versão do FORTRAN.
Declarações e módulos externos
As linguagens Módula-2 e Ada usam o escopo estático como um meio de compartilhar dados entre unidades de programa. Usando o método alternativo de compartilhamento dados, cada módulo pode especificar exatamente os outros módulos para os quais é necessário acesso, nem mais, nem menos.
Em linguagens orientadas a objeto como o C++ e o Java, uma classe pode ser usada para encapsular coleções de dados para ser compartilhadas entre outras classes.
Variáveis globais definidas em outros arquivos de código C incluídos em um programa também podem ser acessadas por funções que as declaram como externas.
Operadores sobrecarregados definidos pelo usuário
Os operadores podem ser sobrecarregados pelo usuário em programas Ada e C++. Como um exemplo disso, considere a seguinte função Ada que sobrecarrega o operador de multiplicação (*) para computar o produto pontual de dois arrays. O produto pontual de dois arrays é a soma dos produtos de cada um dos pares de elementos correspondentes de dois arrays.
Temos que saber quando a sobrecarga de um operador pode ser boa, ou, pode-se ter muita sobrecarga, mas, isso é uma questão de gosto. O argumento contra a demasiada sobrecarga de operador é principalmente uma questão de legibilidade.
Co-rotinas
Uma co-rotina é um tipo especial de subprograma. Em vez da relação mestre-escravo entre o subprograma chamador e o chamado que existe nos subprogramas convencionais, as co-rotinas chamadoras e chamadas estão em uma base mais igual. De fato, o mecanismo de controle de co-rotinas frequentemente é chamado modelo de controle unitário simétrico.
As co-rotinas tem múltiplos pontos de entrada, controladas pelas próprias co-rotinas. Elas também tem os meios para manter seus status entre as ativações.
Tipicamente, as co-rotinas são criadas em uma aplicação por uma unidade de programa chamada unidade-mestra, a qual não é uma co-rotina. Quando criadas, elas executam seu código de inicialização e, depois, retornam o controle a essa unidade-mestra. Se uma execução de co-rotina atingir o final de sua seção de código, o controle será transferido para a unidade-mestra que as criou.
Um exemplo de problema que pode ser resolvido com coleção de co-rotinas é a simulação de um jogo de cart.
Post por: Hamilton & Ingrid
Sistemas de Informação IV

Um comentário:

  1. Não sei se entendi muito bem, mas o que entendi foi que, subprogramas permitem a divisão de um só programa em módulos diferentes, ou seja, cada um pode ser desenvolvido de forma separada, já que um programa é totalmente independente do(s) outro(s), e que estes subprogramas podem posteriormente serem integrados a um só programa.

    Parabéns pelo post!!!

    ResponderExcluir