Baixe o app para aproveitar ainda mais
Prévia do material em texto
GCC 105 – LINGUAGENS DE PROGRAMAÇÃO I AULA 8 – Avaliação de Expressões II 1º Semestre de 2015 Prof. Janderson Rodrigo de Oliveira Universidade Federal de Lavras Departamento de Ciência da Computação Expressões Relacionais e Booleanas • Expressões relacionais – Um operador relacional é aquele que compara os valores de seus dois operandos. – Uma expressão relacional tem dois operandos e um operador relacional. – O valor de uma expressão relacional é booleano, exceto quando valores booleanos não têm um tipo específico incluído na linguagem. Expressões Relacionais e Booleanas • Expressões relacionais – Os operadores relacionais são comumente sobrecarregados para uma variedade de tipos. – A operação que determina a verdade ou falsidade de uma expressão relacional depende dos tipos dos operandos. – Os tipos dos operandos que podem ser usados para operadores relacionais são tipos numéricos, cadeias e tipos ordinais. Expressões Relacionais e Booleanas • Expressões relacionais – A sintaxe dos operadores relacionais para igualdade e desigualdade difere entre as linguagens de programação. Exemplo: operador de desigualdade. Linguagens baseadas em C != Ada /= Lua ~= Fortran .NE ou <> Expressões Relacionais e Booleanas • Expressões relacionais – JavaScript e PHP possuem dois operadores relacionais adicionais: === e !==. – São similares aos seus operadores relativos, == e !=, mas que previnem seus operandos de sofrerem coerção. Exemplo em JavaScript: “7” == 7 “7” === 7 Verdadeiro Falso Expressões Relacionais e Booleanas • Expressões relacionais – Os operadores relacionais sempre têm precedência mais baixa do que os operadores aritméticos, de forma que, em expressões como: – as expressões aritméticas são avaliadas primeiro. a + 1 > 2 * b Expressões Relacionais e Booleanas • Expressões booleanas – Expressões booleanas consistem em variáveis booleanas, constantes booleanas, expressões relacionais e operadores booleanos. – Os operadores normalmente incluem aqueles para as expressões E, OU e NÃO (AND, OR e NOT), e algumas vezes para o OU exclusivo (XOR). – Operadores booleanos normalmente recebem apenas operandos booleanos e produzem valores booleanos. Expressões Relacionais e Booleanas • Expressões booleanas – Na matemática de álgebras booleanas, os operadores E e OU devem ter uma precedência igual. – De acordo com isso, os operadores E e OU de Ada tem a mesma precedência. – Entretanto, nas linguagens baseadas em C atribuem uma maior precedência para o E em relação ao OU. Expressões Relacionais e Booleanas • Expressões booleanas – Expressões aritméticas podem ser operandos de expressões relacionais, e expressões relacionais podem ser operandos de expressões booleanas. – Logo, as três categorias de operadores devem ser colocados em diferentes níveis de precedência, relativas umas às outras. Expressões Relacionais e Booleanas • Expressões booleanas – A precedência dos operadores aritméticos, relacionais e booleanos as linguagens baseadas em C é: Mais alta ++ e -- pós-fixados + e - unários, ++ e -- pré-fixados, ! *, /, % + e - binários >, <, >=, <= ==, != && Mais baixa || Expressões Relacionais e Booleanas • Expressões booleanas – Algumas linguagens, incluindo Perl e Ruby, fornecem dois conjuntos dos operadores lógicos binários, && e and para o E; || e or para o OU. – Uma diferença entre estes dois conjuntos é que as versões por extenso têm precedência menor. – Além disso, and e or têm precedência igual, mas && tem precedência maior do que ||. Expressões Relacionais e Booleanas • Expressões booleanas – A legibilidade dita que uma linguagem deve incluir um tipo booleano, em vez de simplesmente usar tipos numéricos em expressões booleanas. – Algumas detecções de erros é perdida no uso de tipos numéricos, porque qualquer expressão numérica, seja pretendida ou não, é um operando legal para um operador booleano. Avaliação em Curto-Circuito • Uma avaliação em curto-circuito de uma expressão é uma avaliação na qual o resultado é determinado sem avaliar todos os operandos e/ou operadores. • Por exemplo, o valor da expressão aritmética: é independente do valor de (b / 13 - 1) se a for igual a 0. • Entretanto, em expressões aritméticas, esse atalho não é facilmente detectado durante a execução, então ele nunca é tomado. (13 * a) * (b / 13 - 1) Avaliação em Curto-Circuito • O valor da expressão booleana: é independente da segunda expressão relacional se a < 0. • Diferentemente do caso das expressões aritméticas, esse atalho pode ser facilmente descoberto durante a execução. • Para ilustrar um problema em potencial com a avaliação que não é em curto-circuito de expressões booleanas, suponha que Java não usasse avaliação em curto-circuito. (a >= 0) && (b < 10) Avaliação em Curto-Circuito • Considere o cenário em que chave não está presente em vetor. • Se chave não estiver em vetor, o programa terminará com uma exceção de índice fora da faixa. indice = 0; while ( (indice < tamanhoVetor) && (vetor[indice] != chave) ) indice = indice + 1; Avaliação em Curto-Circuito • Se uma linguagem fornece avaliação em curto-circuito de expressões booleanas e ela é usada, isso não é um problema. • Uma linguagem que fornece avaliação em curto-circuito de expressões booleanas e que também tem efeitos colaterais em expressões permite que erros sutis ocorram. Exemplo em Java (possui avaliação em curto-circuito e efeitos colaterais): (a > 0) && ( (b++) / 3) Avaliação em Curto-Circuito • Nessa expressão, b é modificado apenas quando a <= 0. • Se o programador assumiu que b seria modificado toda vez em que essa expressão fosse avaliada durante a execução (e a corretude do programa dependesse disso), o programa falharia. • Nas linguagens baseadas em C, os operadores E e OU usuais, && e ||, respectivamente, são avaliados em curto-circuito. Avaliação em Curto-Circuito • Entretanto, os operadores E e OU bit a bit – & e |, respectivamente – não são avaliados em curto-circuito nas linguagens baseadas em C. • Todos os operadores lógicos de Ruby, Perl e Python são avaliados em curto-circuito. • Melhor estratégia: Ada – define duas versões diferentes para os operadores E e OU: uma versão para avaliar expressões em curto-circuito e outra para avaliar expressões sem empregar o curto-circuito. Sentenças de Atribuição • A sentença de atribuição é uma das construções centrais em linguagens imperativas. • Ela fornece o mecanismo pelo qual o usuário pode mudar dinamicamente as vinculações de valores a variáveis. • Há diversas formas diferentes de formular sentenças de atribuição. Sentenças de Atribuição • Atribuição simples – Praticamente todas as linguagens de programação usadas atualmente usam o sinal de igualdade para o operador de atribuição. – Todas estas linguagens usam algo diferente de um sinal de igualdade para o operador de igualdade relacional, para evitar confusão com seu operador de atribuição. Sentenças de Atribuição • Alvo Condicionais – Perl permite alvos condicionais em sentenças de atribuição. – Equivale a: ($flag ? $count1 : $count2) = 0 if ($flag) { $count1 = 0; } else { $count2 = 0 } Sentenças de Atribuição • Operadores de atribuição compostos – Um operador de atribuição composto é um método de atalho para especificar uma forma de atribuição comumente necessária. – A forma de atribuição que pode ser abreviada com essa técnica tem a variável de destino aparecendo também como o primeiro operando na expressão no lado direito, como em: a = a + b Sentenças deAtribuição • Operadores de atribuição compostos – A sintaxe desses operadores de atribuição é a concatenação do operador binário com o operador =. Por exemplo: – Equivale a: soma += valor; soma = soma + valor; Sentenças de Atribuição • Operadores de atribuição unários – As linguagens baseadas em C, Perl e JavaScript, incluem dois operadores aritméticos unários especiais que são atribuições abreviadas. – Eles combinam operações de incremento e decremento com atribuição. – Os operadores ++ para incremento e -- para decremento, podem ser usados tanto em expressões quanto para formar sentenças de atribuição autocontidas de um único operador. Sentenças de Atribuição • Operadores de atribuição unários – Eles podem aparecer como operadores pré-fixados, que precedem os operandos, ou como operadores pós-fixados, que seguem os operandos. – Na sentença de atribuição: o valor de contador é incrementado em uma unidade e então atribuído a soma. soma = ++ contador; Sentenças de Atribuição • Operadores de atribuição unários – Equivalente a: – Se o mesmo operador for usado como um operador pós-fixado, como em: – A atribuição do valor de contador a soma ocorre primeiro; e só então contador é incrementado. contador = contador + 1; soma = contador; soma = contador ++; Sentenças de Atribuição • Operadores de atribuição unários – Equivalente a: soma = contador; contador = contador + 1; Sentenças de Atribuição • Atribuição como uma expressão – Nas linguagens baseadas em C, Perl e JavaScript, a sentença de atribuição produz um resultado, que é o mesmo que o valor atribuído ao alvo. – Ela pode, dessa forma, ser usada como uma expressão e como um operando em outras expressões. – Esse projeto trata o operador de atribuição de forma bastante similar a qualquer outro operador binário, exceto que ele tem o efeito colateral de modificar seu operando da esquerda. Sentenças de Atribuição • Atribuição como uma expressão – Por exemplo, em C, é comum escrever sentenças como: – Nessa sentença, o próximo caractere do arquivo da entrada padrão é obtido com getchar e atribuído a variável ch. – O resultado é então comparado com a constante EOF. – Se ch não for igual a EOF, a sentença composta é executada. while ( (ch = getchar() ) != EOF ) { ... } Sentenças de Atribuição • Atribuição como uma expressão – Note que a atribuição deve estar entre parênteses. – Nas linguagens que oferecem suporte a este recurso, a precedência do operador de atribuição é menor do que dos operadores relacionais. – Sem o parênteses, o novo caractere seria comparado com EOF primeiro. Então, o resultado dessa comparação, seja 0 ou 1, seria atribuído a ch. Sentenças de Atribuição • Atribuição de listas – Diversas linguagens de programação recentes, incluindo Perl, Ruby e Lua, fornecem sentenças de atribuição de múltiplos alvos e fontes. – Por exemplo, em Perl é possível escrever: – Se os valores de duas variáveis precisam ser trocados, isso poderia ser feito com uma única atribuição: ($primeiro, $segundo, $terceiro) = (20, 40, 60); ($primeiro, $segundo) = ($segundo, $primeiro); Sentenças de Atribuição • Atribuição de modo misto – Fortran, C, C++ e Perl usam regras de coerção para atribuição de modo misto similares àquelas que tais linguagens usam para expressões de modo misto. – Ada não permite atribuições de modo misto. – Java e C# permitem a atribuição de modo misto apenas se a coerção requerida é de alargamento. Então, um valor int pode ser atribuído a uma variável float, mas não o contrário.
Compartilhar