Finalidade → especificar computações aritméticas
Origem na Matemática
- Define características e estabelece convenções
- Define os operandos e expressões possíveis
Com o que se preocupar
- Ordem de avaliação dos operadores
- Precedência
- Associatividade
- Uso de parênteses
- Ordem de avaliação dos operandos (e efeitos colaterais)
- Sobrecarga e mesclagem dos modos
Ordem de Avaliação dos Operadores
- Depende da precedência e da associatividade
Resultado pode ser diferente
a = 3; b = 4; c = 5;
r = a + b * c
\pause Tipo do operador dita a ordem de precedência
- Precedência similar dos operadores matemáticos
- Projetistas especificam ordens diferentes para não comuns
Regras de Precedência geral para operadores clássicos
- Parênteses
- Exponenciação
- Multiplicação e divisão
- Adição e subtração
Exemplo
r = a + b * c + d / e + (f + g)
- Como implementar a avaliação desta expressão?
- Uma forma possível é através de uma estrutura hierárquica
Como avaliar a - b + c - d
?
Regras de associatividade
- Aplicadas quando há duas ou mais ocorrências de operadores de mesmo nível de precedência
- Dois tipos
- Associatividade da esquerda para a direita
- o contrário
Em LPs comuns, sempre da esquerda para a direita
Algumas exceções
- Exponenciação (em Fortran e Ada)
-
$++$ e$–$ prefixados (C, C++) -
$+$ e$-$ unários (C, C++)
E importa a ordem em casos como este?
a + b + c + d
\pause Matematicamente não
- Com a representação discreta pode importar
Uso de parênteses controla a ordem de avaliação
Problemas relacionados com o seu uso
- Escrita de expressões mais tediosa
- Acabam com a legibilidade do código
Preocupação quanto aos operandos
- Variáveis – como minimizar o acesso à memória?
- Constantes – em memória ou fixos no código?
- Parênteses – avaliadas antes das outras
- Funções – seu resultado deve ser recuperado
\pause
Preocupações quanto aos efeitos colaterais
Acontece quando uma função modifica um de seus parâmetros ou uma variável global
- Não há em funções puras no paradigma funcional
- Não há com passagem por valor
\pause Suponha que
int a = 10;
int foo (int &x) { //passagem por referência
x = x/2;
return x;
}
\pause Se tiveremos a + foo(a)
, o que acontece?
- Se avaliarmos
foo(a)
primeiro - Se avaliarmos a variável
a
primeiro
Impedir/Eliminar funções que modifiquem vars. externas
- Como programar sem variáveis globais?
\pause Optar por uma única ordem de avaliação (Java)
- Como otimizar o programa?
\pause Aceitar somente quando as funções não modificam os valores dos outros operandos na mesma expressão (Fortran 77)
- Como garantir isso?
\pause Não fazer nada
- Fica a critério do compilador/interpretador
Mesmo símbolo, múltiplos propósitos
x = &y;
z = x & y;
Conjuntos distintos, com resultados distintos
float media;
int soma, cont;
media = soma/cont;
- \pause Pascal tem dois operadores de divisão