notas-de-aula- Schneider
29 pág.

notas-de-aula- Schneider

Disciplina:Linguagens de Programação I252 materiais732 seguidores
Pré-visualização11 páginas
não têm relação com o
espaço ocupado em memória pelos tipos envolvidos. A definição dessa classificação não é precisa,
assim, nem sempre é conveniente classificar determinada conversão em uma dessas categorias.

Podem ser explícitas ou implícitas. Às vezes, o termo coerção é usado somente para as conversões
implícitas. O autor deste texto usa a palavra coerção como sinônimo de conversão.

A maioria das linguagens oferece instruções para conversão de tipos, que podem ser apresentadas

prof. Bruno Schneider 11

Notas de Aula de GCC105 - BCC e BSI - UFLA

como elementos sintáticos da linguagem ou na forma de funções.

2.3.3.1 Coerção em expressões
Se uma linguagem permite expressões aritméticas com operadores que usam operandos de tipos
diferentes (expressões de modo misto), devem definir conversões implícitas.

Em muitas linguagens as conversões implícitas de estreitamento causam a emissão de avisos por
parte do compilador.

Não existe um consenso a respeito do que é melhor: restringir a flexibilidade das expressões ou
deixar a verificação de tipos sob a responsabilidade do programador.

As coerções de subfaixas de inteiros para inteiros, ou de inteiros pequenos para inteiros são muito
comuns.

Coerções mais profundas como a conversão de strings em valores numéricos são mais comuns em
linguagens com vinculação dinâmica de tipos.

2.3.4 Operadores relacionais e expressões booleanas
Linguagens oferecem operadores relacionais para construir expressões booleanas. Operadores
relacionais retornam um valor do tipo booleano (se ele for um tipo da linguagem).

Operadores relacionais costumam estar disponíveis para tipos numéricos, strings e ordinais
(enumerados e subfaixas).

Expressões booleanas são aquelas que retornam um tipo booleano (o operador mais externo é
relacional).

Um efeito interessante da falta do tipo booleano na linguagem C é validade da expressão (a > b > c)
que não tem o mesmo significado que se espera pela notação matemática.

2.3.5 Avaliação em curto-circuito
Muitas vezes, para se determinar o valor de uma expressão, não é preciso avaliar todos os
operadores dela. Quando a avaliação de expressões é feita levando em conta esses casos especiais,
ela é dita uma avaliação em curto-circuito.

A avaliação em curto-circuito é incomum para expressões aritméticas, mas é comum para
expressões booleanas.

Na avaliação em curto-circuito, funções que mudam o estado de algo e retornam valor podem não
ser chamadas, não causando qualquer mudança de estado. Por outro lado, nas avaliações em circuito
longo, operações ilegais podem ser executadas caso o programador esperasse ver apenas uma parte
da expressão processada.

Algumas linguagens tem operadores específicos para os dois tipos de avaliação (ex.: and then/or
eles de Ada). Usar operadores lógicos bit a bit pode prover flexibilidade (ex.: & e | no C, C++ e
Java).

2.3.6 Operador de atribuição
A atribuição é a instrução que realiza cópia de valores de um armazenamento para outro. É uma das
características básicas da programação imperativa pois possibilita a alteração do estado de um

prof. Bruno Schneider 12

Notas de Aula de GCC105 - BCC e BSI - UFLA

processamento.

Uma atribuição envolve dois elementos:
• uma expressão cujo valor pode ser encontrado, chamada de right value (valor direito) já que

costuma aparecer do lado direito da atribuição nas várias regras de sintaxe e
• uma expressão cujo armazenamento pode ser encontrado, chamada de left value (valor

esquerdo).

Frequentemente as linguagens têm regras sintáticas que impedem elementos como constantes
(literais ou não) e expressões aritméticas (variáveis temporárias) de serem usadas onde se espera um
left value.

2.3.6.1 Atribuição simples
É a forma tradicional, em que uma variável recebe o valor de uma expressão. O operador pode
retornar algo ou não.

2.3.6.2 Alvos múltiplos
Várias variáveis recebem o valor de uma expressão. Esse efeito pode ser imitado pelos operadores
que retornam referências.

2.3.6.3 Alvos condicionais
Usando o operador ternário ?:, C++ e Java permitem alvos condicionais.

2.3.6.4 Atribuição composta
É a atribuição usando expressões em que a variável modificada faz parte da expressão (ex.: += em
C, C++ e Java).

2.3.6.5 Operador unário de atribuição
Incrementam e decrementam, como nas linguagens C, C++ e Java.

2.3.6.6 Atribuição como função
O operador de atribuição pode retornar valor como em C, C++ e Java.

Facilitam a atribuições seguidas de teste. Permitem imitar os alvos múltiplos. Reduzem a
legibilidade e, na falta do tipo booleano, reduzem a capacidade do compilador para detectar erros.

Java não tem o problema das atribuições no meio de expressões (de C e C++) porque tem o tipo
booleano e o uso de número em lugar de booleanos causa erros de tipo.

2.3.7 Atribuição de modo misto
As linguagens podem permitir atribuição do valor de um tipo à uma variável de outro tipo. Pode-se
usar coerção.

prof. Bruno Schneider 13

Notas de Aula de GCC105 - BCC e BSI - UFLA

2.4 Controle de fluxo
O controle de fluxo é a determinação da ordem de execução das instruções de um programa. As
regras de precedência e associatividade de operadores, vistas na seção 2.3.1, são uma forma de
controle de fluxo. As linguagens também precisam prover formas de controlar o fluxo entre os
vários blocos de programa.

O controle de fluxo é tão fundamental nos programas imperativos quanto a atribuição. Mecanismos
de seleção de instruções permitem produzir repetições ou escolher entre várias formas de computar
um valor.

Duas formas de controle (o desvio condicional/incondicional) são necessárias. Duas formas são
recomendadas: o desvio condicional e a repetição com teste no início. As linguagens proporcionam
mais formas, porém não muitas, para que não fiquem complicadas demais.

As instruções de controle devem ter entrada única e saída única. As entradas múltiplas são perigosas
enquanto que as saídas múltiplas apenas reduzem a legibilidade.

2.4.1 Instruções compostas
São blocos de instruções tratados como se fossem uma única instrução. Eliminam a necessidade de
instruções delimitadas e são especialmente interessantes para as estruturas de controle de fluxo.
Também auxiliam a manter uma “lógica positiva”, que destaca os casos especiais.

Algumas linguagens exigem que instruções compostas apareçam em determinados contextos.

Quase sempre, as instruções compostas são demarcas por algum elemento sintático (ex.: begin/end),
porém algumas linguagens modernas usam a endentação para demarcação.

2.4.2 Instruções de seleção
Permitem escolher caminhos de execução.

Do ponto de vista do hardware, geralmente existem dois tipos de instrução de controle de fluxo:
desvio condicional e incondicional. Esses dois elementos podem ser combinados em instruções de
seleção mais abstratas. As linguagens procuram esconder o desvio incondicional do programador,
oferecendo seletores.

2.4.2.1 Seleção unidirecional e bidirecional
O seletor unidirecional “if (teste) instrução” é uma abstração quase direta do desvio condicional do
hardware.

Para desincentivar o uso de desvio incondicional, as linguagens oferecem instruções compostas ou
algum tipo de marcador para o final das instruções.

O seletor bidirecional “if (teste) then instrução else instrução” é o principal seletor em todas as
linguagens. Geralmente o seletor unidirecional incorpora algum elemento sintático (como o “then”)
de forma a se tornar uma versão especial do seletor bidirecional.

O teste é quase sempre uma expressão booleana.

prof. Bruno Schneider 14

Notas de Aula de GCC105 - BCC e BSI - UFLA

2.4.2.2 Seletores aninhados
Quando uma instrução de seleção pode ser aninhada em outra, podemos ter ambiguidade. Essa
ambiguidade pode ser resolvida por:

• uma regra da linguagem (ex.: Pascal/C++ - o else é sempre vinculado ao if mais recente);

• sintaxe da linguagem (ex.: Algol60 - o if não pode ser usado como instrução