3 ms·
Please note that, despite the misleading title, TFA is about the precedence of bitwise operators & and | with respect to the comparison operators (== and all th
by teo_zero 3y ago
Please note that, despite the misleading title, TFA is about the precedence of bitwise operators & and | with respect to the comparison operators (== and all the others). In particular it was asked to Ritchie why the former are weaker than the latter in C, a rule generally considered a mistake because it makes it impossible to write common expressions like
if (addr & mask == 0)
without adding extra parentheses:
if ((addr & mask) == 0)
TFA is not about the relative precedence between & and | (which is well understood, although disputed, and has mathematical basis), or between && and || (which mimics & and |). And TFA is not even about the precedence of the logical operators && and || vs. the comparison operators.
I'm writing this because I've seen a lot of comments that, while interesting in themselves, completely misunderstood the premise.
- goto11 3y agoThank you for this additional context. So in short, bitwise operators have lower precedence than comparisons to allow you to write: if (a==b & c==d) ... but of course, this means you can't write bitwise checks like this: if (addr & mask == 0) ... The problem could theoretically have been solved when the shortcut operators were introduced, by increasing the precedence of & and | to be higher than comparisons, but have the shortcut operators be lower. So you would be able to write both: if (a==b && b==c) ... if (addr & mask == 0) ... But this was not done due to concerns of backward compatibility with existing code, since now every expression using the old pattern would subtly change semantics. E.g. the first example would now be parsed as: if ((a==(b & c))==d) ...
- MaxBarraclough 3y ago> you could write [...] but of course, this means you can't write I found this rather difficult to read. You could write those expressions. They're legal C code. Whether they will have the expected semantics will depend on, well, what you expected. The more general problem is code that relies too heavily on precedence rules in the first place. Precedence-related bugs and readability issues are easily avoided, just use parentheses. As I mentioned in another comment in this thread, some languages force the programmer to do this.
- goto11 3y agoSure, you can use parentheses everywhere, but the code would be quite noisy. Do you think this: ((window.location).href) == foo; is more readable than: window.location.href == foo;
- MaxBarraclough 3y agoI said code that relies too heavily on precedence rules. Your example doesn't do so. In another comment [0] I mentioned that the Ada and Pony languages force the programmer to use parentheses when the expression would otherwise be confusingly reliant on precedence rules. Neither language requires unwieldy overuse of parentheses. This C programming style advice article similarly recommends a middle-ground approach. [1] I agree that unnecessary syntactic noise is bad (although this is essentially true by definition, as it's always a derogative). It can harm readability and make bugs more likely. [0] https://news.ycombinator.com/item?id=38886613 https://news.ycombinator.com/item?id=38886613 [1] https://wiki.sei.cmu.edu/confluence/display/c/EXP00-C.+Use+parentheses+for+precedence+of+operation https://wiki.sei.cmu.edu/confluence/display/c/EXP00-C.+Use+p...
- leereeves 3y agoWhy was it important to allow you to write: if (a==b & c==d) I always thought using the bitwise operator as if it were a logical operator was simply a mistake, even though it works because false is 0 and true is 1. Edit: Mea culpa for reading and responding to the comments before the article.
- nathan_douglas 3y agoTo be fair, Dennis says: >The priorities of && || vs. == etc. came about in the following way. I think it takes some serious concentration to tease out that he is indeed trying to explain what you indicated. Either that, or my brain is just thoroughly cooked. I'm not arguing with you -- I think you're absolutely right -- but man, Dennis made it hard on us here
- smcameron 3y ago> && and || (which mimics & and |) I've always thought of it as mimicking * (multiplication) and + (addition), and you can actually use * and + in place of && and || if you wanted to (not advisable, though the idea can be used in expressions to produce branchless code, common technique in GPU shader code). I used to use this trick in TI99/4a BASIC which lacked "AND" and "OR" in "IF" statements, but because boolean expressions evaluated to integer 1 and 0 for true and false, multiplication and addition could serve as AND and OR.
- teo_zero 3y agoBut remember that * and + don't short-circuit. This won't work: found = (p != NULL) * (*p ! = 0);