Is it true that people write crazy code with overlapping side effects while still being cool?

Original author: Raymond Chen
  • Transfer
Your attention is invited to a translation of an article by Raymond Chen from The Old New Thing 's blog , devoted to code problems that rely on the procedure for evaluating expressions - and to all those who write foo (i ++, a [i]);
The order in which expressions are calculated is determined by the particular implementation, unless the language guarantees a certain order of calculations. If, in addition to the result, evaluating an expression causes changes in the runtime, then it is said that the expression has side effects.
In our internal C # newsletter, a debatable question arises regularly regarding the correct interpretation of such constructions:

a -= a *= a;
p[x++] = ++x;

In response, I ask:
But who writes such code with a straight face? It's one thing when you write this, trying to win the "International Obfuscated C Code Contest", or if you want to write a puzzle - but in both cases you understand that you are doing something non-standard. That, really there is someone who writes a - = a * = a and p [x ++] = ++ x; and thinks to himself, “Damn it, I’m writing really cool code!”
To which Eric Lippert answers me: "Yes, such people definitely meet." As an example, he cited one successful book by a popular author who firmly believed that the shorter the code, the faster it works. So, imagine - sales of this book are already over 4 million copies and continue to grow. The author of this book tried to shove several side effects into each expression at once, densely strewn with conditional ternary operators; the thing is that he sincerely believed that the speed of the program is proportional to the number of semicolons used in it - and that every time a programmer declares a new variable, God kills the puppy.

Of course, with some effort, you can teach the compiler to analyze such code and issue a warning like this: " The result of this operation may vary depending on the calculation order ." However, if you make such a decision, you will have to deal with other problems.

Firstly, there will be a large number of false positives. Let's say you write the following code:

total_cost = p->base_price + p->calculate_tax();

This code will raise a warning: the compiler will see that the calculate_tax method is not constant (const), so he will worry that the method may change the base_price variable - in which case it will matter whether you consider the tax on the original base_price to be the base price, or by already changed. Now, suppose that you know (and this knowledge is not available to the compiler) that the method of calculation of the tax calculate_tax updates the value of the local variable tax ( tax ) in the object, but does not change the basic price; so for you this warning will be a false alarm.

As you have already seen for yourself, the problem here is that in the event of the addition of such a warning, an awfully large number of false positives await us - as a result of which the developers will simply turn off this warning.

Well, well, take a step back, and let's warn only about the most egregious cases - only when the variable is changed and calculated in the same expression. " Warning: Expression relies on computation order ."

Take the super-smart programmer Expert Joe: he knows that his code is flawless, and the compiler is weak. “Well, it’s obvious that the variable is incremented first, then it is used to calculate the index of the array, and then the search result in the array is saved back to the variable. There is no conflict of calculation order. Dumb compiler! ". As a result, super-smart programmer Expert Joe will turn off this warning, finding it useless. Well, our Expert Joe is still a hopeless case, and we are not worried about him.

But let's take another programmer, Beginner Joe - in fact, he will not even understand the essence of this warning. “Well ok, let's see. I compiled this function five times, and each time I got the same result. The result looks reliable to me. It seems that the warning was false. ” Thus, it is precisely those who should have benefited from this warning that do not always have sufficient knowledge to understand it.

Of course, some time passes, and this question pops up in the newsletter again. Someone will surely ask why the expression x ^ = y ^ = x ^ = ydoesn't work in C #, although it works in C ++. Here is another proof that some people write code that relies on several side effects at once - and these same people sincerely believe that their code is obvious and guaranteed to work.

Link to the original
Link to the discussion

Also popular now: