What are bitwise shift (bit-shift) operators and how do they work?

后端 未结 11 1444
生来不讨喜
生来不讨喜 2020-11-21 04:46

I\'ve been attempting to learn C in my spare time, and other languages (C#, Java, etc.) have the same concept (and often the same operators) ...

What I\'m wondering

11条回答
  •  情深已故
    2020-11-21 05:08

    Bitwise operations, including bit shift, are fundamental to low-level hardware or embedded programming. If you read a specification for a device or even some binary file formats, you will see bytes, words, and dwords, broken up into non-byte aligned bitfields, which contain various values of interest. Accessing these bit-fields for reading/writing is the most common usage.

    A simple real example in graphics programming is that a 16-bit pixel is represented as follows:

      bit | 15| 14| 13| 12| 11| 10| 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1  | 0 |
          |       Blue        |         Green         |       Red          |
    

    To get at the green value you would do this:

     #define GREEN_MASK  0x7E0
     #define GREEN_OFFSET  5
    
     // Read green
     uint16_t green = (pixel & GREEN_MASK) >> GREEN_OFFSET;
    

    Explanation

    In order to obtain the value of green ONLY, which starts at offset 5 and ends at 10 (i.e. 6-bits long), you need to use a (bit) mask, which when applied against the entire 16-bit pixel, will yield only the bits we are interested in.

    #define GREEN_MASK  0x7E0
    

    The appropriate mask is 0x7E0 which in binary is 0000011111100000 (which is 2016 in decimal).

    uint16_t green = (pixel & GREEN_MASK) ...;
    

    To apply a mask, you use the AND operator (&).

    uint16_t green = (pixel & GREEN_MASK) >> GREEN_OFFSET;
    

    After applying the mask, you'll end up with a 16-bit number which is really just a 11-bit number since its MSB is in the 11th bit. Green is actually only 6-bits long, so we need to scale it down using a right shift (11 - 6 = 5), hence the use of 5 as offset (#define GREEN_OFFSET 5).

    Also common is using bit shifts for fast multiplication and division by powers of 2:

     i <<= x;  // i *= 2^x;
     i >>= y;  // i /= 2^y;
    

提交回复
热议问题