Buscar

Avaliação de Expressões em Linguagens de Programação

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 40 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 40 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 40 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

GCC 105 – LINGUAGENS DE 
PROGRAMAÇÃO I
AULA 7 – Avaliação de Expressões 
1º Semestre de 2015
Prof. Janderson Rodrigo de Oliveira
Universidade Federal de Lavras
Departamento de Ciência da Computação
Introdução
• Expressões são os meios fundamentais de especificar 
computações em uma linguagem de programação.
• É crucial para um programador entender tanto a sintaxe 
quanto a semântica de expressões da linguagem sendo 
utilizada.
• Para entender a avaliação de expressões, é necessário estar 
familiarizado com as ordens de avaliação de operadores e 
operandos, ditadas pelas regras de associatividade e de 
precedência da linguagem.
Introdução
• Outras questões relacionadas à semântica de expressões são:
– As diferenças de tipos;
– Coerções;
– Avaliação em curto-circuito.
• A essência de linguagens imperativas é o papel dominante das 
sentenças de atribuição. O propósito de uma sentença de 
atribuição é modificar o valor de uma variável.
• Uma parte integral de todas as linguagens imperativas é o 
conceito de variáveis cujos valores mudam durante a 
execução de programas.
Expressões Aritméticas
• A avaliação de expressões aritméticas similar àquelas 
encontradas na matemática, na ciência e nas engenharias foi 
um dos principais objetivos das primeiras linguagens de 
programação de alto nível.
• A maioria das características das expressões aritméticas em 
linguagens de programação foi herdada de convenções que 
evoluíram na matemática.
Expressões Aritméticas
• Em linguagens de programação, as expressões aritméticas 
consistem em:
– Operadores;
– Operandos;
– Parênteses;
– Chamadas a funções.
• Um operador pode ser:
– Unário, por possuir um único operando;
– Binário, por possuir dois operandos;
– Terciário, por possuir três operandos.
Expressões Aritméticas
• Na maioria das linguagens de programação imperativas, os 
operandos binários usam a notação convencional (infixa). 
Uma exceção é Perl, possuindo alguns operadores pré-fixados.
• O propósito de uma expressão aritmética é especificar uma 
computação aritmética. Tal processo necessita realizar duas 
ações:
– Obter os operandos, normalmente a partir da memória;
– Executar nos operandos as operações aritméticas especificadas.
Ordem de Avaliação de Operadores
• A ordem de avaliação dos operadores de uma linguagem é 
definida pelas:
– Regras de precedência dos operadores;
– Regras de associatividade dos operadores.
• Precedência
– O valor de uma expressão depende ao menos parcialmente da 
ordem de avaliação dos operadores da expressão. Considere a 
expressão:
a + b * c
Ordem de Avaliação de Operadores
• Precedência
– Em vez de simplesmente avaliar os operadores em uma 
expressão da esquerda para a direita ou da direita para a 
esquerda, os matemáticos desenvolveram o conceito de colocar 
os operadores em uma hierarquia de prioridades de avaliação.
– As regras de precedência de operadores para avaliação de 
expressões definem a ordem pela qual os operadores de 
diferentes níveis de precedência são avaliados (conforme visto 
pelo projetista da linguagem).
– As regras para as linguagens imperativas comuns são todas 
iguais, porque são baseadas nas da matemática.
Ordem de Avaliação de Operadores
• Precedência
– De modo geral, tem-se que: a exponenciação tem a mais alta 
precedência, seguida pela multiplicação e divisão no mesmo 
nível, depois pela adição e subtração binária no mesmo nível.
– Muitas linguagens também incluem versões unárias da adição e 
da subtração.
• Adição unária: não tem operação associada e não faz efeito 
em seu operando;
• Subtração unária: modifica o sinal de seu operando. Pode 
aparecer no início de uma expressão ou em qualquer lugar 
dentro dessa, desde que seja entre parênteses para prevenir 
que fique ao lado de outro operador.
Ordem de Avaliação de Operadores
• Precedência
– As precedências dos operadores aritméticos de algumas 
linguagens de programação bastante usadas são:
– A precedência diz respeito a apenas algumas das regras para a 
ordem de avaliação de operadores; as regras de associatividade 
são outras.
Ruby Linguagens Baseadas em C Ada
Mais alta ** ++ e --pós-fixados **, abs
+ e – unários ++ e -- pré-fixados, + e -
unários 
*, /, mod, rem
*, /, % *, /, % + e – unários
Mais baixa + e - binários + e - binários + e - binários
Ordem de Avaliação de Operadores
• Associatividade
– Considere a expressão:
– Se os operadores de adição e subtração têm o mesmo nível de 
precedência, as regras de precedência nada dizem a respeito da 
ordem de avaliação dos operadores nessa expressão.
– Quando uma expressão contém duas ocorrências adjacentes de 
operadores com mesmo nível de precedência, a questão sobre 
qual operador é avaliado primeiro é respondida pelas regras de 
associatividade da linguagem.
a - b + c - d
Ordem de Avaliação de Operadores
• Associatividade
– Um operador pode ter:
• Associatividade à direita: a ocorrência mais a direita é 
avaliada primeiro;
• Associatividade à esquerda: a ocorrência mais a esquerda é 
avaliada primeiro.
– A associatividade nas linguagens imperativas mais usadas é da 
esquerda para a direita, exceto que o operador de 
exponenciação (quando fornecido) associa da direita para a 
esquerda.
Ordem de Avaliação de Operadores
• Associatividade
– Na expressão em Java:
– o operador esquerdo é avaliado primeiro. Mas a exponenciação
em Fortran e Ruby é associativa à direita, então na expressão:
– o operador direito é avaliado primeiro.
– Em Visual Basic, o operador de exponenciação (^) é associativo 
à esquerda.
a - b + c
A ** B ** C
Ordem de Avaliação de Operadores
• Associatividade
– As regras de associatividade para algumas linguagens 
imperativas bastante utilizadas são:
Linguagem Regra de Associatividade
Ruby
Esquerda: *, /, +, -
Direita: **
Linguagens Baseadas em C
Esquerda: *, /, %, + binário, - binário
Direita: ++, --, - unário, + unário
Ada
Esquerda: Todos, exceto **
Não associativo: **
Ordem de Avaliação de Operadores
• Parênteses
– Os programadores podem alterar as regras de precedência e de 
associatividade colocando parênteses em expressões. 
– Uma parte com parênteses de uma expressão têm precedência 
em relação às suas partes adjacentes sem parênteses.
– Por exemplo, apesar da multiplicação ter precedência em 
relação à adição, na expressão
– a adição será avaliada primeiro.
(A + B) * C
Ordem de Avaliação de Operadores
• Parênteses
– Linguagens que permitem parênteses em expressões 
aritméticas podem dispensar todas as regras de precedência e 
simplesmente associar todos os operadores da esquerda para a 
direita ou da direita para a esquerda.
– O programador seria responsável por especificar a ordem 
desejada da avaliação.
– Vantagem: simplicidade – nem o autor nem os leitores dos 
programas precisariam se lembrar de regras de precedência ou 
de associatividade.
Ordem de Avaliação de Operadores
• Parênteses
– Desvantagem: torna a escrita de expressões mais tediosa e 
compromete seriamente a legibilidade do código.
– Mesmo assim, essa foi a escolha feita pelo projetista da 
linguagem APL.
Ordem de Avaliação de Operadores
• Expressões condicionais
– Sentenças if-then-else podem ser usadas para realizar uma 
atribuição baseada em expressão condicional. Por exemplo:
– Nas linguagens baseadas em C, esse código poderia ser 
especificado mais convenientemente em uma sentença de 
atribuição usando uma expressão condicional na forma:
if (contador == 0)
media = 0;
else
media = soma/contador;
Ordem de Avaliação de Operadores
• Expressões condicionais
– onde expressão_1 é interpretada como uma expressãobooleana. Se a expressão_1 for avaliada como verdadeira, o 
valor da expressão inteira é o valor da expressão_2; caso 
contrário, será o valor da expressão_3. 
– No nosso exemplo teríamos:
expressão_1 ? expressão_2 : expressão_3
media = (contador == 0) ? 0 : soma/contador;
Ordem de Avaliação de Operadores
• Expressões condicionais
– Note que o sinal ? é usado em expressões condicionais como 
um operador ternário.
– Expressões condicionais podem ser usadas em qualquer lugar 
de um programa (em uma linguagem baseada em C) nos quais 
qualquer outra expressão possa ser usada.
– Além das linguagens baseadas em C, expressões condicionais 
são fornecidas em Perl, JavaScript e Ruby.
Ordem de Avaliação de Operandos
• Uma característica de projeto de expressões menos discutida 
é a ordem de avalição dos operandos.
• As variáveis em expressões são avaliadas por meio da 
obtenção de seus valores a partir da memória.
• As constantes são algumas vezes avaliadas da mesma 
maneira. Em outros casos, podem ser parte da instrução de 
linguagem de máquina e não requerer uma busca em 
memória.
Ordem de Avaliação de Operandos
• Se um operando é uma expressão entre parênteses, todos os 
operadores que ela contém devem ser avaliados antes de seu 
valor poder ser usado como um operando.
• Se nenhum dos operandos de um operador tiver efeitos 
colaterais, a ordem de avaliação dos operandos é irrelevante.
Ordem de Avaliação de Operandos
• Efeitos colaterais
– Um efeito colateral de uma função, chamado de um efeito 
colateral funcional, ocorre quando a função modifica um de 
seus parâmetros ou uma variável global.
– Considere a expressão:
– Se fun não tem o efeito colateral de modificar a, a ordem de 
avaliação dos dois operandos não tem efeito no valor da 
expressão.
a + fun(a)
Ordem de Avaliação de Operandos
• Efeitos colaterais
– No entanto, se funmodifica a, existe um efeito. Considere a 
seguinte situação: fun retorna 10 e modifica o valor de seu 
parâmetro para 20. Suponha que tivéssemos o seguinte:
– Se o valor de a for obtido primeiro, seu valor é 10 e o valor da 
expressão é 20.
– Se o segundo operando for avaliado primeiro, o valor de a é 20 e 
o valor da expressão é 30.
a = 10
b = a + fun(a)
Ordem de Avaliação de Operandos
• Efeitos colaterais
– O seguinte exemplo em C ilustra o mesmo problema quando 
uma função modifica uma variável global.
int a = 5;
int fun(){
a = 17;
return 3;
} //Fim de fun
voidmain(){
a = a + fun();
printf(“Mensagem: %d\n”, a);
} //Fim de man
Ordem de Avaliação de Operandos
• Efeitos colaterais
– Execução:
– Funções matemáticas não tem efeitos colaterais, porque não 
existe a noção de variáveis na matemática. O mesmo é verdade 
para linguagens de programação funcionais puras.
Ordem de Avaliação de Operandos
• Efeitos colaterais
– Existem duas opções para o problema de avaliação de 
operandos e efeitos colaterais:
1. Proibir efeitos colaterais funcionais – difícil de implementar e 
elimina alguma flexibilidade para o programador. Por exemplo: 
proibiria o acesso a variáveis globais em funções;
2. Definir que os operandos em expressões sejam avaliados em 
uma ordem especifica – impede que técnicas de otimização de 
código reorganizem a avaliação de operandos.
Ordem de Avaliação de Operandos
• Transparência referencial e efeitos colaterais
– O conceito de transparência referencial está relacionado e é 
afetado pelos efeitos colaterais funcionais.
– Um programa tem a propriedade de transparência referencial se 
quaisquer duas expressões no programa que têm o mesmo 
valor puderem ser substituídas uma pela outra em qualquer 
lugar no programa, sem afetar a ação deste.
– Considere o exemplo a seguir.
Ordem de Avaliação de Operandos
• Transparência referencial e efeitos colaterais
– Se a função fun não tem efeitos colaterais, resultado1 e 
resultado2 serão iguais.
– Entretanto, suponha que fun tem o efeito colateral de adicionar 
1 a b ou a c. Então resultado1 não será igual a resultado2.
– Esse efeito colateral viola a transparência referencial.
resultado1 = (fun(a) + b)/(fun(a) - c )
temp = fun(a);
resultado2 = (temp + b)/(temp - c)
Ordem de Avaliação de Operandos
• Transparência referencial e efeitos colaterais
– Existem vantagens de se ter programas transparentes 
referencialmente.
– Principal vantagem: torna a semântica muito mais fácil de 
entender do que a dos programas não transparentes 
referencialmente.
– Ser transparente, referencialmente, torna uma função 
equivalente a uma função matemática, em termos de facilidade 
de entendimento.
Operadores Sobrecarregados
• Operadores aritméticos são usados para mais de um 
propósito.
• Por exemplo, o sinal de + é usado para especificar a adição 
tanto de inteiros quanto de valores de ponto flutuante.
• Algumas linguagens – Java, por exemplo – também o usam 
para concatenação de cadeias.
• O uso múltiplo de um operador é chamado de sobrecarga de 
operadores, uma prática considerada aceitável, desde que 
nem legibilidade e confiabilidade sejam comprometidas.
Operadores Sobrecarregados
• Algumas linguagens de programação capazes de suportar 
tipos abstratos de dados, como C++ e C#, permitem ao 
programador sobrecarregar símbolos de operadores.
• Por exemplo, suponha que um usuário quer definir o 
operador * entre um inteiro escalar e uma matriz de inteiros 
de forma a significar que cada elemento da matriz seja 
multiplicado por esse escalar.
• Tal operador pode ser definido escrevendo um subprograma 
chamado * responsável por essa nova operação.
Operadores Sobrecarregados
• O compilador escolherá o significado correto quando um 
operador sobrecarregado é especificado, baseado nos tipos 
dos operandos, assim como ocorre com os operadores 
sobrecarregados definidos pela linguagem.
• Quando usada com bom-senso, a sobrecarga de operadores 
definida pelo usuário pode melhorar a legibilidade.
Adic_Matrizes(Multipl_Matrizes(A,B), Multipl_Matrizes (C,D))
A * B + C * D
Operadores Sobrecarregados
• Por outro lado, a sobrecarga definida pelo usuário também 
pode ser prejudicial à legibilidade.
• Por exemplo, nada previne que um usuário defina + como 
sendo uma multiplicação.
• Outra consideração é o processo de construir um sistema de 
software a partir de módulos criados por grupos diferentes. 
Grupos diferentes podem sobrecarregar um mesmo operador 
de formas diferentes.
Conversões de Tipos
• As conversões de tipos são de duas categorias:
– Estreitamento: uma conversão de estreitamento converte um 
valor para um tipo que não pode armazenar aproximações 
equivalentes a todos os valores do tipo original. Por exemplo, 
converte um double para float em Java.
– Alargamento: converte um valor para um tipo que pode incluir 
ao menos aproximações de todos os valores do tipo original. Por 
exemplo, converter um int para float em Java.
Conversões de Tipos
• Conversões de alargamento são quase sempre seguras, 
mantendo a magnitude do valor convertido.
• Conversões de estreitamento nem sempre são seguras –
algumas vezes a magnitude do valor convertido é modificada 
no processo.
• Apesar de as conversões de alargamento serem normalmente 
seguras, elas podem resultar em uma precisão reduzida.
Conversões de Tipos
• Conversões de tipo podem ser explícitas ou implícitas 
(coerções).
• Coerção em expressões
– Uma das decisões de projeto relacionadas às expressões 
aritméticas é se um operador pode ter operandos de tipos 
diferentes.
– Linguagens que permitem tais expressões, chamadas de 
expressões de modo misto, devem definir convenções para 
conversões de tipo para operandos implícitas porque os 
computadores não tem operações bináriasque recebam 
operandos de tipos diferentes.
Conversões de Tipos
• Coerção em expressões
– Os projetistas de linguagens não entraram em um acordo a 
respeito da questão das coerções em expressões aritméticas.
– Contra: preocupação com problemas de confiabilidade que 
podem resultar de tais coerções, porque elas reduzem os 
benefícios da verificação de tipos.
– A favor: preocupação com a flexibilidade que resulta de tais 
restrições.
– A questão é: os programadores devem se preocupar com essa 
categoria de erros ou o compilador deve detectá-los?
Conversões de Tipos
• Coerção em expressões
– Exemplo: de quem é a responsabilidade por reconhecer o 
seguinte erro? 
int a;
float b, c, d;
...
d = b * c;
int a;
float b, c, d;
...
d = b * a;
Desejado: Implementado:
Conversões de Tipos
• Conversão de tipo explícita
– A maioria das linguagens fornece alguma capacidade para a 
realização de conversões explícitas, tanto de alargamento 
quanto de estreitamento.
– Nas linguagens baseadas em C, as conversões de tipo explícitas 
são chamadas de casts.
– Para especificar um cast, o tipo desejado é colocado entre 
parênteses imediatamente antes da expressão a ser convertida.
(int) angle

Outros materiais