Hmmm... I would rather make the intent obvious by using && and || for booleans and & and | for bitwise operations, and let the compiler figure out how to save the branch, if it is a good idea. Compilers are pretty smart these days.hgm wrote:I use & and | in stead of && and || quite often. This can save you branches, and branches that are not there can also not be mispredicted.lucasart wrote:Now I'm very careful with C operators. Mistying a '&&' into a '&', or making wrong assumptions about operator precednece and default associativity, has cost me quite a few hours of debugging already.
Possible history table improvement
Moderators: hgm, Rebel, chrisw
-
- Posts: 931
- Joined: Tue Mar 09, 2010 3:46 pm
- Location: New York
- Full name: Álvaro Begué (RuyDos)
Re: Possible history table improvement
-
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: Possible history table improvement
The C operator precedence table is way too big and complex to fit in my brain. I never try to learn and remember it, but accept that I do not want to remember it. If I did learn it off by heart, I would be too tempted to write obscure code, by abusing my knowledge of it, which is not a good thing.Harald wrote:And when I wrote that I thought that & had a higher priority than <.
That was also wrong. We learn: Just use a lot of () and be careful with & in conditions.
I only remember the stuff that I use most often, and the rest (un-obvious) I prefer to use () to (i) be sure it works (ii) make the code more self-obvious.
But sometimes I read other people's code, and some people love to abuse their knowledge of C operator precedence to write obscure code. So I just Google for "C operator precedence".
For example, I've noticed that Marco likes to use the right-to-left associativity of the ternary operator '? :' to chain conditions (and save lines of code) like this:
Code: Select all
a = b ? c : d ? e : f;
Code: Select all
a = b ? c : (d ? e : f);
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
-
- Posts: 931
- Joined: Tue Mar 09, 2010 3:46 pm
- Location: New York
- Full name: Álvaro Begué (RuyDos)
Re: Possible history table improvement
The rules of C are the way they are for a reason. Well, sometimes it's a bad reason. But in the case of the ternary operator, you can read concatenated ternary operators as "if this is true, this value; otherwise if this other thing is true, this other value, etc.". It's as easy to read as an if-else if-...-else block.lucasart wrote:For example, I've noticed that Marco likes to use the right-to-left associativity of the ternary operator '? :' to chain conditions (and save lines of code) like this:which is equivalent toCode: Select all
a = b ? c : d ? e : f;
I learnt this 'trick' reading stockfish, but I prefer not writing code like that, as it takes too much brain power to read.Code: Select all
a = b ? c : (d ? e : f);
-
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: Possible history table improvement
I don't advocate not using '?:' or arbitrarly limiting ourselves to not chain the ternary operator. All I'm saying is that chaining '?:' without () is a bit obscure (in reality a,b,c,d,e,f are more complex expressions...). So I simply preferAlvaroBegue wrote:The rules of C are the way they are for a reason. Well, sometimes it's a bad reason. But in the case of the ternary operator, you can read concatenated ternary operators as "if this is true, this value; otherwise if this other thing is true, this other value, etc.". It's as easy to read as an if-else if-...-else block.lucasart wrote:For example, I've noticed that Marco likes to use the right-to-left associativity of the ternary operator '? :' to chain conditions (and save lines of code) like this:which is equivalent toCode: Select all
a = b ? c : d ? e : f;
I learnt this 'trick' reading stockfish, but I prefer not writing code like that, as it takes too much brain power to read.Code: Select all
a = b ? c : (d ? e : f);
Code: Select all
a = b ? c : (d ? e : f);
Code: Select all
a = b ? c : d ? e : f;
Some people think that () should be put everywhere to avoid mistakes.
Code: Select all
a = ((b) ? (c) : ((d) ? (e) : (f)));
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
-
- Posts: 931
- Joined: Tue Mar 09, 2010 3:46 pm
- Location: New York
- Full name: Álvaro Begué (RuyDos)
Re: Possible history table improvement
Yeah, those people write in LISP.lucasart wrote:Some people think that () should be put everywhere to avoid mistakes.Code: Select all
a = ((b) ? (c) : ((d) ? (e) : (f)));
I think chaining ternary operators without parentheses is actually preferable. It allows you to do things like this:
Code: Select all
bool operator<(SomeStruct a, SomeStruct b) {
return a.first != b.first ? a.first < b.first
: a.second != b.second ? a.second < b.second
: a.third != b.third ? a.third < b.third
: a.fourth != b.fourth ? a.fourth < b.fourth
: a.fifth < b.fifth;
}