Saltar para o conteúdo
Topos Uranos

Resumo

Esta aula encerra a terceira unidade do curso, dedicada às expressões e seus operadores. Reconstrói a cadeia de conceitos que vai do operador aritmético à função de biblioteca, passando pela árvore da expressão e o tipo de cada nó, as condições e sua álgebra, o curto-circuito, o efeito colateral e a ordem de avaliação, e os bits; separa o que disso vale em qualquer linguagem do que é próprio de C++; reúne o comportamento indefinido da unidade, com o que o compilador detecta, o que o detector detecta e o que ninguém detecta; repete na sua avaliação de saída as habilidades da avaliação de entrada; e termina com seis desafios que combinam a unidade inteira.

Objetivos de aprendizagem

  1. Prever o valor, o tipo e o efeito de qualquer expressão do curso, a partir da sua árvore e das conversões em cada nó.
  2. Escrever e negar condições compostas, e usar o curto-circuito para proteger uma operação que de outro modo careceria de significado.
  3. Reconhecer as expressões que carecem de significado (o catálogo do comportamento indefinido da unidade), dizer que ferramenta detecta cada uma e reescrevê-las sem ele.
  4. Escolher entre a aritmética, os operadores bit a bit e a biblioteca matemática para um cálculo dado, e justificar a escolha.
  5. Separar, no que foi aprendido na unidade, o que vale em qualquer linguagem do que é próprio de C++.

O que a unidade alcançou

A unidade propôs-se ensinar a construir expressões cujo valor se possa prever com certeza: que operação se faz primeiro, de que tipo é o resultado, que efeitos colaterais tem e que expressões não têm significado. O propósito cumpriu-se apoiando-se só no que a introdução declarou como sabido: os tipos da unidade 2, seus intervalos e suas conversões. O programa das seis perguntas com que a introdução colocou o problema pode agora ser lido como o compilador o lê, e corrigido expressão por expressão.

Aritmética

A aula Aritmética estabeleceu o comportamento exato dos cinco operadores aritméticos. A divisão inteira trunca em direção a zero e cumpre a identidade (a / b) * b + a % b == a sempre que o quociente tenha significado, de modo que o resto, quando não é zero, tem o sinal do dividendo; daí que -7 / 2 valha −3-3 e -7 % 2 valha −1-1, e que a imparidade se pergunte com n % 2 != 0. Relacionou-o com o resto euclidiano, ((a % b) + b) % b para b>0b > 0, e usou ambos para decompor quantidades. Ensinou a desenhar a árvore de uma expressão segundo a precedência e a associatividade, e a decidir o tipo em cada nó pelas conversões aritméticas usuais. Fechou com os quocientes sem significado (a divisão inteira por zero e o menor inteiro dividido por −1-1) e com o estouro de um resultado intermediário, que basta para o comportamento indefinido ainda que o resultado final caiba.

Relações e lógica

A aula Relações e lógica ensinou que uma condição é uma expressão de tipo bool, com seu lugar na árvore: as relações ligam menos que a aritmética, && mais que ||, e ! mais que todas. Ensinou a traduzir enunciados em condições e a reconhecer as que compilam com outro significado, como 1 < x < 5 e day == 6 || 7. Mostrou que && e || avaliam seu segundo operando só se o primeiro não decide, e que esse curto-circuito permite proteger uma operação com uma guarda à sua esquerda. Terminou com as leis de De Morgan, que negam uma condição composta, e com seu limite: com um valor não numérico, !(a < b) não equivale a a >= b.

Atribuição, efeitos colaterais e comportamento indefinido

A aula Atribuição, efeitos colaterais e comportamento indefinido distinguiu o valor de uma expressão do seu efeito: a atribuição é uma expressão que vale o que foi atribuído e muda uma variável, e x++ vale o valor anterior enquanto ++x vale o novo. Mostrou que a árvore de uma expressão não fixa a ordem em que se calculam seus ramos, de modo que dois efeitos sobre uma mesma variável, ou um efeito e uma leitura, sem ordem entre eles, deixam a expressão sem significado, e precisou o que C++17 ordenou e o que deixou sem especificar. Reuniu o catálogo dos quatro graus (definido, definido pela implementação, não especificado e indefinido), explicou que o compilador raciocina supondo que o programa não tem comportamento indefinido, e disse, para cada caso do catálogo, que ferramenta o detecta.

Bits e biblioteca matemática

A aula Bits e biblioteca matemática ensinou que um inteiro é também uma sequência de bits: &, | e ^ aplicam um conectivo a cada coluna, ~ inverte todos os bits, e os deslocamentos multiplicam e dividem por potências de 2, com a condição de que a quantidade do deslocamento não seja negativa nem alcance a largura do tipo. Com eles construiu as máscaras que consultam, ligam, desligam e alternam um bit. Advertiu que esses operadores ligam menos que as relações, de modo que x & 1 == 0 não pergunta o que parece, e que ^ não é a potência. Fechou com a biblioteca: <cmath>, <numbers>, <numeric> e <bit> dão cálculos corretos e testados, com suas próprias precondições, como a do valor absoluto, que não existe para o menor inteiro.