Three ways to read a number for a BitInputStream I'm trying to learn how to write more readable code without introducing easily avoidable performance killers.

This is part of a BitInputStream Java class I'm experimenting with. There are code parts before and after this provided segment to read less than 8 bits from iBuffer if data is not aligned to bytes - that's why aNumberOfBits is needed to know how many bits have to be read later on.

I think variant 3 below is best when implemented in Java, but variant 1 may be worth the more complex formula for slightly better (theoretical) performance in C for realtime applications.

Variant 1:

int i = aNumberOfBits / 8;
aNumberOfBits -= i * 8;
for (; i &gt; 0; --i) {
   iBuffer = iIs.read();
   if (iBuffer == -1) {
      throw new EOFException();
   }
   value = (value &lt;&lt; 8) | iBuffer;
}


Variant 2 (obviously worse performant on most CPUs?):

for (int i = aNumberOfBits / 8; i &gt; 0; --i) {
   iBuffer = iIs.read();
   if (iBuffer == -1) {
      throw new EOFException();
   }
   value &lt;&lt;= 8;
   value |= iBuffer;
   aNumberOfBits -= 8;
}


Variant 3:

for (int i = aNumberOfBits / 8; i &gt; 0; --i) {
   iBuffer = iIs.read();
   if (iBuffer == -1) {
      throw new EOFException();
   }
   value = (value &lt;&lt; 8) | iBuffer;
}
aNumberOfBits %= 8;


Now what about variant 2: should aNumberOfBits be decremented by 8 in the loop for a better understanding why it is decremented? (And isn't shifting value and then ORing the next part of data even more complicated to read than doing it in one step?)
If you are so concerned about performance, then you should run a benchmark.  I would bet that there is no appreciable difference in performance, as the task is going to be IO-bound rather than CPU-bound.  A much bigger impact on performance would be, for example, whether the input stream is buffered.  Therefore, you should just pick the code that looks the best.  I personally prefer a variant of variant 3.

It seems that you are interested in the values of value and aNumberOfBits after the loop.  Since i is unimportant, let's just ditch it.  Also, iBuffer seems to be a temporary variable, so its scope should be limited to the loop.

Finally, let's get rid of the Hungarian notation!

for (; bitCount &gt;= 8; bitCount -= 8) {
    int b = input.read();
    if (b == -1) {
        throw new EOFException();
    }
    value = (value &lt;&lt; 8) | b;
}


What might make a performance impact is reading a byte[] array at once instead of a byte at a time.  Handling possible buffer underruns correctly would be a pain, though, so I don't recommend it here.