Resumo
Esta aula abre a terceira unidade do curso, dedicada às expressões e seus operadores. Explica para que serve a unidade: ensinar a construir expressões cujo valor se possa prever com certeza, sabendo que operação se faz primeiro, de que tipo é o resultado, que efeitos colaterais tem e que expressões não têm significado; apresenta suas quatro aulas e o fio que as une, desde a aritmética inteira e real até os bits e a biblioteca matemática, passando pelas condições e pelo catálogo do comportamento indefinido; recorda o que a unidade dá por sabido da segunda, que é o tipo de cada dado, seus limites e suas conversões; formula o problema que a unidade resolve, o de um programa que compila sem um único aviso e cujas respostas a seis perguntas escolares estão todas erradas, quando não faltam; e mostra aonde conduz, nas unidades seguintes e no curso Programação em C++ II.
Objetivos de aprendizagem
- Descrever a sequência de conteúdos da unidade e explicar o que cada aula traz à seguinte.
- Recordar o necessário da unidade 2 (os tipos inteiros e reais, seus intervalos, o estouro e as conversões) e revisá-lo se for preciso.
- Antecipar, com um exemplo, que o valor de uma expressão depende de regras de avaliação (a precedência, o tipo dos operandos, a ordem dos efeitos) que nem sempre coincidem com as da matemática escolar.
- Reconhecer o que se espera saber fazer ao terminar a unidade, e distingui-lo do que se aprenderá nas unidades seguintes.
Avaliação de entrada
Antes de percorrer a unidade, convém medir o ponto de partida. Esta avaliação é uma autoavaliação: não se pontua, e seu único propósito é orientar o estudo. As quatro primeiras perguntas verificam o que a unidade dá por sabido da segunda: a divisão entre inteiros, a escrita em base 2, a subtração sem sinal e o estouro com sinal. As seis seguintes tocam, na ordem das aulas, as ideias centrais da unidade, e várias delas partem da matemática escolar ou da lógica elementar. Ninguém é obrigado a acertá-las ainda, e em duas delas “ainda não sei” é uma resposta honesta: cada resposta, certa ou não, explica o ponto e nomeia a aula que o trata. As mesmas habilidades voltam a ser medidas no final, na aula de síntese.
Antes de começar a unidade, meça seu ponto de partida. É uma autoavaliação breve: não recebe nota e seu resultado fica guardado apenas no seu navegador.
Pergunta 1De unidades anterioresUm programa declara
const double r{7 / 2};e escrever. O que aparece?Crê que o tipo da variável decide como se divide; quem o decide é o tipo dos operandos.Crê que a divisão inteira arredonda; ela descarta a parte decimal.O valor 3 é constante e se representa exatamente numdouble: não há estreitamento a rejeitar.A divisão7 / 2é entre inteiros e dá o quociente inteiro, 3; só depois esse 3 é convertido emdouble. O tipo dos operandos decide a operação, não o tipo da variável que recebe o resultado. A aula 3.1 converte esta observação numa regra geral: o tipo se decide em cada nó da expressão.Pergunta 2De unidades anterioresComo se escreve o número 13 em base 2, com oito bits?
Soma mal os pesos: .Escreve os restos das divisões sucessivas na ordem em que saem; eles se leem do último para o primeiro.Essa configuração é 26, o dobro de 13: os bits estão deslocados uma posição.Cada posição pesa o dobro da que está à sua direita: os uns ocupam as posições de peso 8, 4 e 1. A aula 3.4 opera diretamente sobre esses bits, de modo que convém lê-los com desenvoltura.Revisar: Os inteiros e sua representação
Pergunta 3De unidades anterioresO que escreve
std::println("{}", 0u - 1);com umunsigned intde 32 bits?Não leva em conta o sufixou: um tipo sem sinal não tem negativos.Confunde a aritmética sem sinal, definida módulo , com o estouro com sinal.Crê que a subtração para no menor valor do tipo; ela dá a volta.A aritmética sem sinal é módulo : . O resultado está definido, e por isso nenhum detector o assinala. A unidade o reencontra nas conversões de uma expressão mista e nos operadores bit a bit, que se escrevem com tipos sem sinal.Revisar: Os inteiros e sua representação
Pergunta 4De unidades anterioresUm programa executa
int count{std::numeric_limits<int>::max()};e depoiscount = count + 1;. O que o padrão garante sobre o valor decount?Confunde o que às vezes se observa com o que o padrão garante; a volta ao mínimo é o que fazem os tipos sem sinal, não os com sinal.Ignora o limite do tipo: esse número não cabe numintde 32 bits.O compilador não conhece os valores que o programa terá ao ser executado; quase sempre compila sem dizer nada.A soma tem uma pré-condição, que o resultado caiba no tipo, e fora dela o padrão não promete nada. O detector do curso detém o programa; sem ele, pode ser escrita qualquer coisa. A aula 3.3 reúne este caso com os demais de sua espécie num catálogo.Revisar: Os inteiros e sua representação
Pergunta 5Quanto valem e ?
Opera da esquerda para a direita sem atender à precedência do produto.Ignora os parênteses da segunda expressão.Atribui a cada expressão o valor da outra: inverte o efeito dos parênteses.O produto liga mais que a soma: em se multiplica primeiro, e os parênteses alteram essa ordem. C++ segue a mesma convenção, e a aula 3.1 a estende à divisão, ao resto e à associatividade, com a árvore da expressão como instrumento.Revisar: Aritmética
Pergunta 6Segundo o teorema da divisão da matemática, com o resto sujeito a , quais são o quociente e o resto de por ?
É o que C++ calcula, mas não cumpre : o resto da matemática não é negativo.Não verifica a identidade: , não .Também não cumpre a identidade: .O teorema exige com , e esses dois números são os únicos que o cumprem. C++, por outro lado, trunca o quociente em direção ao zero:-7 / 2vale e-7 % 2vale . A aula 3.1 explica a diferença e ensina a obter o resto da matemática a partir do de C++.Revisar: Aritmética
Pergunta 7Qual é a negação de “chove e faz frio”?
Nega cada parte sem mudar o conectivo: isso afirma muito mais que a negação, porque exclui também o dia seco e frio.Nega só uma das partes.Diz o mesmo que a segunda opção, com o mesmo erro.A negação de uma conjunção é a disjunção das negações: é uma das leis de De Morgan. Basta que falte uma das duas coisas para que a afirmação seja falsa. A aula 3.2 aplica a mesma lei às condições de um programa.Revisar: Relações e lógica
Pergunta 8O que escreve
std::println("{}", 3 < 5);?Crê que o valor lógico se escreve como número; com o marcador{},std::printlnescreve a palavra.Crê que a expressão se escreve como texto; o que se escreve é seu valor.É, sim: uma comparação é uma expressão de tipobool.Uma comparação é uma expressão como qualquer outra: tem um valor, de tipobool, estd::printlno escreve comotrueoufalse. A aula 3.2 parte desta observação: uma condição se calcula, e por isso tem precedência, árvore e álgebra.Revisar: Relações e lógica
Pergunta 9Depois de
int a{5};eint b{a++ * 2};, quanto valemaeb?É uma resposta honesta: a aula 3.3 ensina a diferença entre o valor de uma expressão e seu efeito, e a avaliação de saída voltará a perguntá-lo.Esquece o efeito:a++incrementaa.Usa o valor novo dea; o incremento pós-fixo dá o valor anterior.A expressãoa++tem um valor, o queatinha (5), e um efeito, que deixaaem 6. O produto usa o valor, não o efeito. A aula 3.3 ensina a separar as duas coisas, e a reconhecer quando dois efeitos numa mesma expressão a deixam sem significado.Revisar: Atribuição, efeitos colaterais e comportamento indefinido
Pergunta 10O que escreve
std::println("{}", 2 ^ 3);?É uma resposta honesta: a aula 3.4 o explica, e a avaliação de saída voltará a perguntá-lo.Lê o acento circunflexo como potência, como na notação de muitas calculadoras; em C++ ele não o é.Lê-o como produto.Em C++ o acento circunflexo não é a potência, mas o OU exclusivo bit a bit: e diferem só no bit de peso 1, de modo que o resultado é 1. C++ não tem operador de potência; a aula 3.4 ensina quando usarstd::powe quando um deslocamento.Revisar: Bits e biblioteca matemática
Carregando o conteúdo…