Reputation: 79509
I'm currently dissecting through the ol' Doom engine source code, and came across an interesting line:
counter = (++counter)&(MAX_VALUE-1);
It looks like a way to increment a counter without going over a certain number, but I have a tricky time doing bitwise operations in my head, so I whipped up a quick console project to try this out, and lo and behold, it works beautifully.
I deduce the above way is more efficient than an if() statement, especially if the code is executed rapidly, for example, within a loop, where performance within a real-time game is crucial.
I'm trying to figure out the order of operations the compiler uses to execute this line. If the increment '++' operator is placed after the 'counter', it will always remain zero. It only works if the increment is used as a prefix ("++counter"), but even still, if I write it out with pen and paper, I get the arbitrary result of the bitwise AND operation, not a counter that increments.
It seems the bitwise operation is calculated, and then the increment is performed, but I'm stumped figuring out why, any ideas?
Upvotes: 0
Views: 625
Reputation: 12057
The formula
counter = (++counter)&(MAX_VALUE-1);
has undefined behaviour, see CoryKramer's answer.
The formula
counter = (counter + 1)&(MAX_VALUE - 1);
works only for MAX_VALUEs that are equal to a power of 2. Only then the value MAX_VALUE - 1
has this form in binary:
000...000111...111
When such a value is used in a AND operation, it "truncates" the higher bits of the other value, and has the effect of wrapping around when the other value reaches MAX_VALUE.
I think the normal modulo operation is just as fast on modern hardware, and does not have the restriction mentionend above:
counter = (counter + 1)%MAX_VALUE;
Upvotes: 0
Reputation: 118001
While the parentheses have higher precedence than operator ++
or bitwise AND
(operator &
), there are no defined sequence points in your right-hand side. So your code exhibits undefined behavior.
If you remove the operator++
what this is intending to do is
(counter + 1)&(MAX_VALUE-1);
If you consider MAX_VALUE
to be 32
then MAX_VALUE-1
in binary is
11111
So if you have a larger value than that and use &
any bits left of bit 5 (from the right) will be cleared
0000011111 // assume this is MAX_VALUE - 1
1100110110 // assume this is counter + 1
__________
0000010110
The result would be true
if any of the bits less than or equal to MAX_VALUE - 1
were 1
.
Upvotes: 1