Skip to content
Topos Uranos

Summary

This lesson closes the third unit of the course, devoted to expressions and their operators. It reconstructs the chain of concepts that runs from the arithmetic operator to the library function, passing through the expression tree and the type of each node, conditions and their algebra, the short circuit, side effects and the order of evaluation, and bits; it separates what of all this holds in any language from what is specific to C++; it gathers the undefined behavior of the unit, with what the compiler detects, what the sanitizer detects and what nobody detects; it repeats in its exit assessment the skills of the entry assessment; and it ends with six challenges that combine the whole unit.

Learning objectives

  1. Predict the value, the type and the effect of any expression of the course, from its tree and from the conversions at each node.
  2. Write and negate compound conditions, and use the short circuit to protect an operation that would otherwise have no meaning.
  3. Recognize the expressions that have no meaning (the catalog of the undefined behavior of the unit), state which tool detects each one and rewrite them without it.
  4. Choose between arithmetic, bitwise operators and the math library for a given calculation, and justify the choice.
  5. Separate, in what was learned in the unit, what holds in any language from what is specific to C++.

What the unit achieved

The unit set out to teach how to build expressions whose value can be predicted with certainty: which operation is done first, what type the result has, what side effects it has and which expressions have no meaning. The purpose has been fulfilled relying only on what the introduction declared it took for granted: the types of unit 2, their ranges and their conversions. The program of the six questions with which the introduction posed the problem can now be read as the compiler reads it, and corrected expression by expression.

Arithmetic

The lesson Arithmetic established the exact behavior of the five arithmetic operators. Integer division truncates toward zero and satisfies the identity (a / b) * b + a % b == a whenever the quotient has a meaning, so that the remainder, when it is not zero, has the sign of the dividend; hence -7 / 2 is −3-3 and -7 % 2 is −1-1, and oddness is tested with n % 2 != 0. It related this to the Euclidean remainder, ((a % b) + b) % b for b>0b > 0, and used both to decompose quantities. It taught how to draw the tree of an expression according to precedence and associativity, and how to decide the type at each node by the usual arithmetic conversions. It closed with the quotients without meaning (integer division by zero and the smallest integer divided by −1-1) and with the overflow of an intermediate result, which suffices for undefined behavior even if the final result fits.

Relations and logic

The lesson Relations and logic taught that a condition is an expression of type bool, with its place in the tree: relations bind less tightly than arithmetic, && more tightly than ||, and ! more tightly than all of them. It taught how to translate sentences into conditions and how to recognize those that compile with another meaning, such as 1 < x < 5 and day == 6 || 7. It showed that && and || evaluate their second operand only if the first does not decide, and that this short circuit makes it possible to protect an operation with a guard to its left. It ended with De Morgan’s laws, which negate a compound condition, and with their limit: with a not-a-number value, !(a < b) is not equivalent to a >= b.

Assignment, side effects and undefined behavior

The lesson Assignment, side effects and undefined behavior distinguished the value of an expression from its effect: assignment is an expression whose value is what was assigned and which changes a variable, and x++ yields the previous value while ++x yields the new one. It showed that the tree of an expression does not fix the order in which its branches are computed, so that two effects on the same variable, or an effect and a read, with no order between them, leave the expression without meaning, and it specified what C++17 ordered and what it left unspecified. It gathered the catalog of the four degrees (defined, implementation-defined, unspecified and undefined), explained that the compiler reasons on the assumption that the program has no undefined behavior, and stated, for each case of the catalog, which tool detects it.

Bits and the math library

The lesson Bits and the math library taught that an integer is also a sequence of bits: &, | and ^ apply a connective to each column, ~ inverts all the bits, and the shifts multiply and divide by powers of 2, provided that the shift amount is neither negative nor reaches the width of the type. With them it built the masks that test, set, clear and toggle a bit. It warned that these operators bind less tightly than the relations, so that x & 1 == 0 does not ask what it seems to ask, and that ^ is not exponentiation. It closed with the library: <cmath>, <numbers>, <numeric> and <bit> provide correct and tested calculations, with their own preconditions, such as that of the absolute value, which does not exist for the smallest integer.