Why is the order of calculation of subexpressions not defined in C?

Due to the existence of the priority of performing operations and the rules of associativity, it follows that the algorithm for calculating any expression in C is deterministic.

At the lectures I found this slide: lecture example

What does it mean? What was meant here?

Author: Vitaly, 2018-01-17

3 answers

Look, you have different subexpressions in each expression. The compiler has the right to generate code that will compute them in any order.

For example, if you have the expression

f(x) + g(x)

If the functions f and g output something internally to the console, the order in which the output will be made is not defined.

What is it for? For example, for optimization: if your expression has the same subexpressions, it is convenient to calculate them simultaneously, rather than calculating in order:

f(x * y) + 3 * z / f(3 * x * y)

It can be calculated, for example, as follows:

  • calculate x * y and put it in the register R1
  • call f with the parameter R1, put the result in R2
  • calculate 3 * R1, put the result in R1, because we no longer need the old value
  • call f with the parameter R1, put the result in R3
  • calculate 3 * z, put the result in R1, since neither the expression x * y, nor the expression 3 * x * y we no longer need
  • calculate R1 / R3, put the result in R1
  • add R2 to R1, this is the result of our calculation.

If we had to preserve the order of calculations, we would not be able to remember common subexpressions, and the code would be less efficient.

 3
Author: VladD, 2018-01-17 20:26:28

Due to the existence of the priority of performing operations and the rules of associativity, it follows that the algorithm for calculating any expression in C is deterministic.

This is not true. "Priority and associativity" only defines an abstract syntactic and semantic grouping between operators and operands. But this grouping does not really determine the order of calculation. It is taught in school that expressions" must " be evaluated in order of priority and associativity. in the C language, this is not required at all. We can say that the "school" calculation rules specify a certain "canonical" calculation order, but the compiler is not obliged to follow it as long as it guarantees that the result of the expression matches the canonical one.

In your example, the C language does not guarantee that x * y will be evaluated before d - a. This is, of course, a rather "innocent" uncertainty. But the language also does not guarantee that c * b will be calculated first, and therefore the result is already multiplied by d - a. Perhaps the compiler will first decide to multiply b by d - a. Moreover, the compiler can choose to compute c * b * (d - a) as c * b * d - c * b * a if it so chooses.

Separately, it can be noted that the relevance of the topic of the order of calculation is still due to the fact that expressions in C have not only results, but, possibly, also side effects. This is their essential difference from the "pure" expressions used in mathematics.

 3
Author: AnT, 2018-01-17 20:40:02

That, for example, x*y can be calculated both before c*b*(d-a) and later...

 2
Author: Harry, 2018-01-17 19:41:39