Computing is really all about order. If you can take data, apply an operation to it, and get the same result every single time, then you have a stable and reliable computing system.
So it makes total sense that there is Operator Precedence. This is also called Order of Operations, and it dictates which computations will be performed first, and which will be performed last. To get the same results every time, you must perform addition, multiplication, power functions, bitwise math, and all other calculations in a codified order.
The question I’ve had on my mind lately is, does this matter to us or just the compiler?
Which Would You Do?
As I was banging out some microcontroller code last weekend, I started looking at the number of parenthesis I was using. See, I like total control over what this computer etched into a shard of glass is doing. So I don’t depend on precedence, but this made me wonder if I’m doing it wrong. So I asked on Twitter which of following lines of code people would use:
a |= 1 << 1 + c; a |= 1 << (1 + c);
It is not surprising that everyone grabbed a torch and pitchfork in support of choosing parens at every opportunity. The consensus was that the next person reading the code will have a much easier time and will understand your intent. And that next person is more often than not you — how embarrassing if you can’t work out your own intent. Do yourself a favor and use parenthesis!
He’s Unhappy with Precedence, and He Wrote the Language!
In C it’s easy to understand how this is all built into the syntax. The equals sign assigns a value to a variable, so equals needs to have really low precedence otherwise that assignment will happen before the operations are performed. And function calls must happen before any other operations so there is actually data available to operate upon. It works. I rely on precedence in these two cases and don’t (necessarily) place everything to the right of an equals sign in parentheses. But not every operator is this easy to rely upon.
The funny thing is that these rules didn’t spring to existence at the start of computer languages, but were developed alongside them. The footnotes of Wikipedia’s order of operations article yields an interesting tidbit from Dennis Ritchie, creator of the C language, in his book The Development of the C Language:
Today, it seems that it would have been preferable to move the relative precedences of & and ==, and thereby simplify a common C idiom: to test a masked value against another value, one must write
if ( (a & mask) == b ) ...where the inner parentheses are required but easily forgotten.
In addition to a good chuckle, this article also taught me a new term: infelicity.
Is There a Legit Use for Operator Precedence?
So the big question remains. Why do we teach operator precedence in computer science if popular opinion is almost universally against relying upon it? Is there more value than just base understanding?
The most legitimate use for trusting the compiler to follow the same invisible rules you have in your head is the International Obfuscated C Code Contest which is currently open for entries. That contest’s goal is to produce the hardest to read code and “To show the importance of programming style, in an ironic way.”
But I wonder if there are other interesting uses like writing polyglot code, or compiler specific code. Let us know in the comments below.