2

I have encountered many occasions when I have to use between division operator(divide by 2) or the right shift operator(>>) but I tend to use the division operator assuming that use of bit wise operator will make my code less readable. Is my assumption true?

Is it good practice to use left shift operator and right shift operator in production code instead of multiply by 2 or divide by 2.

Prashant Bhanarkar
  • 930
  • 3
  • 14
  • 32
  • 1
    Write whichever is most clear. Using bitwise operators for an operation that isn't thought of as a bitwise one (I mean every operation boils down to bitwise ones anyway) seems rather unclear. – chris Aug 19 '16 at 14:00
  • At least for unsigned variables this optimization will be done anyway by nearly every compiler. So I think it is not harder to read, but that depends on your team. By the way you could use a `#define` to make it easier to read. – MrSmith42 Aug 19 '16 at 14:01
  • @MrSmith42, If you mean `#define MULTIPLY_BY_TWO(x) ((x) << 1)`, then I would argue it's much better as `constexpr int multiply_by_two(int x) { return x << 1; }`, replacing `int` with whatever fits your needs best. Of course that's beside the point here when you're using one of nearly every compiler. – chris Aug 19 '16 at 14:03
  • After all most of the people have their own preference on that topic, I suggest you to have a look at http://stackoverflow.com/questions/7522346/right-shift-and-signed-integer and http://stackoverflow.com/questions/4009885/arithmetic-bit-shift-on-a-signed-integer before playing with bit shifting. – Deniz Aug 19 '16 at 14:03
  • A discussion about speed differences is here: http://stackoverflow.com/a/6357114/1921273 – MrSmith42 Aug 19 '16 at 14:05

2 Answers2

2

Using the bitwise operators for multiplication or division by 2 is utter madness.

  1. The behaviour of << is undefined for negative signed types.

  2. << and >> have lower precedence than addition and subtraction so it messes up your expressions.

  3. It's unnecessarily obfuscating.

  4. Trust a modern compiler to optimise appropriately.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • As you said 'undefined for negative signed types', therefore a compiler will only optimize this for unsigned types. So make sure you are using unsigned types wherever possible to enable the compiler to make such optimizations. – MrSmith42 Aug 19 '16 at 14:09
  • 1
    @MrSmith42: the undefinedness he is talking about is in the C standard; the compiler knows how the underlying hardware behaves and can usually apply these optimizations happily even on signed types (x86, for example, provides both arithmetic and logical shift opcodes). I've never seen the sign adjust code as a performance bottleneck, so use `unsigned` when it makes sense (typically just for bit fields), not in a dubious quest for microoptimizations. – Matteo Italia Aug 19 '16 at 14:17
  • @Matteo Italia: So you have no problem to make copilor dependent code? I would not rely on a specific compiler when I write programs. So only for unsigned types you can be sure that the optimization is likely to be done by the compiler (if it is an optimization on your architecture at all) and the result is what you expect (independent from a specific compiler). – MrSmith42 Aug 22 '16 at 14:49
  • @MrSmith42: what are you talking about? What I'm advocating is to use division or shift, signed or unsigned *according to logical, intended meaning*, not looking for optimizations. If you are worried about this kind of micro-optimization, profile the code, check the generated assembly and go down the rabbit hole as long as you like. But don't use `unsigned` just because you hope to exploit this kind of behavior. Yes, [divide by two for signed integers is more complicated](https://godbolt.org/g/tLMsrl), no, you shouldn't worry unless you measured it (it's still plenty faster than an `idiv`). – Matteo Italia Aug 22 '16 at 15:45
  • 1
    @Matteo Italia: I agree profiling should always be the first step before trying to optimize. – MrSmith42 Aug 26 '16 at 05:58
2

Integer division by constants is routinely optimized to bit shifts (if by powers of two), multiplication by the "integral reciprocal" and all kind of tricks, so performance should not be a concern.

What matters is to clearly express intent. If you are operating on integers "as numbers" and you divide by something that just happens to be a power of 2 use the division operator.

int mean(int a, int b) {
    return (a+b)/2; // yes overflow blah blah
} 

If instead you are operating on integers as bitfields - for example, you are unpacking a nibble and you need to right shift by 4 to move it in "low" position, or you need to explicitly set some bit -, then use bitwise operators.

void hex_byte(unsigned char byte, char *out) {
    out[0]=byte>>4;
    out[1]=byte&0xf;
} 

unsigned set_bit(unsigned in, unsigned n) {
    return in | (1<<n);
} 

In general, most often you'll use division on signed integers, bitwise operators on unsigned ones.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299