Summary
An expression in C++ can do two different things: yield a value and change the state of the program. x + 1 only yields a value; x = 7 yields a value and, in addition, changes x; x++ yields the value that x had and leaves another one in x. This lesson studies that difference between the value and the effect of an expression: assignment as an expression, compound assignment, increment and decrement in their prefix and postfix forms, and the order in which the parts of an expression are evaluated, which the standard fixes only in part. From this follows the question that organizes the rest of the lesson: what the standard promises about a program. The answer is a catalog of four degrees, from defined to undefined behavior, which gathers all the cases seen so far and says, for each one, what detects it (the compiler, the sanitizer, the library) and what nothing detects.
Learning objectives
- Distinguish the value of an expression from its side effect in assignments, increments and calls.
- Predict the result of
x++and++xused as values, and trace by hand a program with compound assignments. - Recognize expressions that modify a variable twice, or that read and modify it, without an order fixed by the standard, and rewrite them as separate statements.
- Classify a construct as defined, implementation-defined, unspecified or undefined, with an example of each kind.
- Say, for each undefined behavior in the catalog, whether the compiler warns about it, whether the sanitizer or the library stops it, or whether nothing detects it.
The value and the effect
The lesson Arithmetic studied the expression as a tree that reduces to a value: 2 + 3 * 4 is 14, and computing it changes nothing outside the expression itself. The lesson Relations and logic did the same with conditions, whose value is true or false. Now, there are expressions that, besides yielding a value, leave a mark on the state of the program: they change the value of a variable, write to the screen or read from the input. That mark is called a side effect, or simply an effect, and the word “side” does not mean that it matters less: in x = 7 the effect, that x comes to be 7, is precisely what is sought.
If this is so, every expression must be read with two questions: what it yields and what it does. Three examples fix the distinction. count + 1 yields the successor of count and does nothing: count keeps its value. count = 9 yields 9 and makes count equal to 9. std::println("hello") is also an expression, a call to a function, and what matters about it is its effect: writing a line. Functions of one’s own will be studied in the lesson Functions, and there the distinction will reappear: a function that only computes its result is easier to understand and to test than one that, in addition, changes something outside it.
A statement such as count + 1; is valid C++: the value is computed and discarded, so it serves no purpose, and GCC warns about it with -Wunused-value. An expression statement makes sense through its effect. From this it follows that expressions with effects are the ones that move the program forward, and also the ones that demand care, because the effect happens at some moment, and that moment is not always the one the reader assumes.
Loading the content…
Completed
Sign in to save your progress